{"openapi":"3.1.0","info":{"title":"Operentra API","version":"1.0.0","description":"The public REST API for Operentra workspaces.\n\nAuthenticate with `Authorization: Bearer opk_live_...`. Money is a decimal string in the workspace currency, date-only fields are calendar dates, and timestamps are RFC 3339 UTC. Errors are problem+json with a stable `code` — branch on that, never on message text."},"servers":[{"url":"https://app.operentra.com/api"}],"security":[{"ApiKey":[]}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"`employees:read` — Read employee records, excluding sensitive personal and pay data.\n`employees:write` — Create, update and deactivate employee records.\n`employees.sensitive:read` — Read sensitive employee fields: national ID, compensation and bank accounts.\n`org:read` — Read organisation structure: departments, designations, branches, employment types, pay grades, shifts and holidays.\n`org:write` — Create and update organisation structure.\n`attendance:read` — Read attendance records, punches, overtime requests, regularisations, rest-day swaps, shift assignments, geofenced sites and the attendance settings.\n`attendance:write` — Record and amend attendance and punches, decide overtime and regularisation requests, manage rest-day swaps, assign shifts to employees, and manage geofenced sites.\n`leave:read` — Read leave types, balances and applications.\n`leave:write` — Apply for, approve and reject leave.\n`payroll:read` — Read salary components, structures and assignments, payroll runs, entries and their lines, salary slips, and loans with their installments.\n`expenses:read` — Read expense categories, claims and their line items.\n`documents:read` — Read document types and employee documents, employment contracts, and issued HR letters with the requests behind them.\n`assets:read` — Read asset categories, assets, and issue/return assignments.\n`announcements:read` — Read announcement categories and published announcements.\n`documents:write` — Upload and verify employee documents.\n`recruitment:read` — Read job openings, candidates and applications.\n`recruitment:write` — Create and update job openings, candidates and applications.\n`webhooks:manage` — Create, update and delete webhook endpoints, and replay deliveries."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. Always English: `code` is the stable identifier to branch on, never the prose in `title` or `detail`.","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"code":{"type":"string","enum":["missing_credentials","invalid_api_key","api_key_expired","api_key_revoked","ip_not_allowed","workspace_inactive","insufficient_scope","validation_failed","not_found","conflict","plan_upgrade_required","workspace_read_only","rate_limit_exceeded","internal_error","api_not_configured"]},"request_id":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"required_scopes":{"type":"array","items":{"type":"string"}}}},"Employee":{"type":"object","description":"A person employed by the workspace. Related records are referenced by id; child collections are separate sub-resources so that `updated_since` stays truthful.","properties":{"object":{"type":"string","enum":["employee"],"nullable":false,"description":"Always `employee`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_code":{"type":"string","nullable":false,"description":"The workspace's own identifier for this employee, unique within the workspace. READ-ONLY: it is assigned from the workspace numbering settings (prefix and digit count) and cannot be set or changed through the API. Use it as a filter on the list endpoint."},"first_name":{"type":"string","nullable":false,"description":"Given name."},"last_name":{"type":"string","nullable":false,"description":"Family name."},"father_name":{"type":"string","nullable":true,"description":"Father's name, where the workspace records it."},"date_of_birth":{"type":"string","format":"date","nullable":true,"description":"Date of birth."},"gender":{"type":"string","nullable":true,"description":"Gender as recorded."},"marital_status":{"type":"string","nullable":true,"description":"Marital status as recorded."},"nationality":{"type":"string","nullable":false,"description":"Nationality. Empty string when not recorded."},"personal_email":{"type":"string","nullable":true,"description":"Personal email address."},"work_email":{"type":"string","nullable":true,"description":"Work email address."},"phone_primary":{"type":"string","nullable":true,"description":"Primary contact number."},"national_id":{"type":"string","nullable":true,"description":"Government identity number. Its meaning follows the workspace country: CNIC in Pakistan, Emirates ID in the UAE, National Insurance number in the UK. Requires the `employees.sensitive:read` scope."},"department_id":{"type":"string","nullable":false,"description":"Department this employee belongs to."},"designation_id":{"type":"string","nullable":false,"description":"Job title."},"branch_id":{"type":"string","nullable":true,"description":"Office or branch."},"employment_type_id":{"type":"string","nullable":false,"description":"Employment type, e.g. permanent or contract."},"reporting_manager_id":{"type":"string","nullable":true,"description":"The employee this person reports to."},"joining_date":{"type":"string","format":"date","nullable":false,"description":"First day of employment."},"confirmation_date":{"type":"string","format":"date","nullable":true,"description":"Date probation was confirmed."},"probation_end_date":{"type":"string","format":"date","nullable":true,"description":"Scheduled end of probation."},"separation_date":{"type":"string","format":"date","nullable":true,"description":"Last day of employment."},"status":{"type":"string","enum":["new","active","inactive","terminated","resigned","retired"],"nullable":false,"description":"Employment status."},"deleted":{"type":"boolean","nullable":false,"description":"True when the record has been deleted. Deleted employees are excluded unless `include_deleted=true`, and are returned with this flag so a client syncing on `updated_since` can learn about removals."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the employee record itself last changed. Does not move when a child record (address, bank account, document) changes."}}},"Department":{"type":"object","description":"A department. Departments may nest through `parent_id`.","properties":{"object":{"type":"string","enum":["department"],"nullable":false,"description":"Always `department`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Department name."},"code":{"type":"string","nullable":true,"description":"Short code."},"parent_id":{"type":"string","nullable":true,"description":"Parent department, for a nested structure."},"head_employee_id":{"type":"string","nullable":true,"description":"Employee who heads this department."},"cost_center":{"type":"string","nullable":true,"description":"Cost centre reference."},"status":{"type":"string","enum":["active","inactive"],"nullable":false,"description":"Whether the record is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Designation":{"type":"object","description":"A job title.","properties":{"object":{"type":"string","enum":["designation"],"nullable":false,"description":"Always `designation`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Job title."},"code":{"type":"string","nullable":true,"description":"Short code."},"level":{"type":"integer","nullable":false,"description":"Seniority level. Higher is more senior; 0 when unranked."},"pay_grade_id":{"type":"string","nullable":true,"description":"Pay grade this title maps to."},"job_description":{"type":"string","nullable":true,"description":"Free-text job description."},"status":{"type":"string","enum":["active","inactive"],"nullable":false,"description":"Whether the record is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Branch":{"type":"object","description":"An office or site.","properties":{"object":{"type":"string","enum":["branch"],"nullable":false,"description":"Always `branch`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Branch name."},"code":{"type":"string","nullable":true,"description":"Short code."},"address":{"type":"string","nullable":true,"description":"Street address."},"city":{"type":"string","nullable":true,"description":"City."},"phone":{"type":"string","nullable":true,"description":"Contact number."},"email":{"type":"string","nullable":true,"description":"Contact email."},"is_head_office":{"type":"boolean","nullable":false,"description":"True for the workspace’s principal office."},"status":{"type":"string","enum":["active","inactive"],"nullable":false,"description":"Whether the record is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"EmploymentType":{"type":"object","description":"An employment arrangement, e.g. permanent, contract, intern.","properties":{"object":{"type":"string","enum":["employment_type"],"nullable":false,"description":"Always `employment_type`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Name of the arrangement."},"description":{"type":"string","nullable":true,"description":"Free-text description."},"is_residential":{"type":"boolean","nullable":false,"description":"The role includes on-site residence."},"accommodation_provided":{"type":"boolean","nullable":false,"description":"Accommodation is provided."},"meals_provided":{"type":"boolean","nullable":false,"description":"Meals are provided."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"PayGrade":{"type":"object","description":"A salary band.","properties":{"object":{"type":"string","enum":["pay_grade"],"nullable":false,"description":"Always `pay_grade`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Grade name."},"min_salary":{"type":"string","nullable":false,"description":"Bottom of the band, as a decimal string in the workspace currency."},"max_salary":{"type":"string","nullable":false,"description":"Top of the band, as a decimal string in the workspace currency."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Shift":{"type":"object","description":"A working pattern: hours, grace periods and rest days.","properties":{"object":{"type":"string","enum":["shift"],"nullable":false,"description":"Always `shift`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Shift name."},"start_time":{"type":"string","nullable":false,"description":"Start time as HH:MM:SS in the workspace timezone."},"end_time":{"type":"string","nullable":false,"description":"End time as HH:MM:SS in the workspace timezone. Earlier than `start_time` for a shift that crosses midnight."},"break_duration_minutes":{"type":"integer","nullable":false,"description":"Unpaid break within the shift, in minutes."},"grace_period_minutes":{"type":"integer","nullable":false,"description":"Minutes after the start time before an arrival counts as late."},"late_threshold_minutes":{"type":"integer","nullable":false,"description":"Minutes late before the day is marked as a late arrival."},"weekly_off_days":{"type":"array","items":{"type":"integer"},"nullable":false,"description":"Rest days as ISO weekday numbers, where 1 is Monday and 7 is Sunday."},"attendance_mode":{"type":"string","enum":["punch_required","auto_present","punch_not_required"],"nullable":false,"description":"How attendance is captured. `punch_required` expects clock-in and clock-out, `auto_present` marks attendance automatically, and `punch_not_required` tracks neither."},"is_default":{"type":"boolean","nullable":false,"description":"Assigned to new employees when no other shift is chosen."},"status":{"type":"string","enum":["active","inactive"],"nullable":false,"description":"Whether the record is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Holiday":{"type":"object","description":"A non-working day.","properties":{"object":{"type":"string","enum":["holiday"],"nullable":false,"description":"Always `holiday`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Holiday name."},"date":{"type":"string","format":"date","nullable":false,"description":"The date, as a calendar date."},"year":{"type":"integer","nullable":false,"description":"Calendar year the date falls in."},"type":{"type":"string","enum":["public","company","optional","religious"],"nullable":false,"description":"Category of holiday."},"is_recurring":{"type":"boolean","nullable":false,"description":"Repeats annually on the same date."},"branch_id":{"type":"string","nullable":true,"description":"Limits the holiday to one branch. Null applies it workspace-wide."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"LeaveType":{"type":"object","description":"A kind of leave — annual, sick, unpaid. The entitlement attached to it lives on its policy.","properties":{"object":{"type":"string","enum":["leave_type"],"nullable":false,"description":"Always `leave_type`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"code":{"type":"string","nullable":false,"description":"Short code, unique within the workspace."},"color":{"type":"string","nullable":false,"description":"Hex colour used to render this type in calendars."},"is_paid":{"type":"boolean","nullable":false,"description":"Whether days taken under this type are paid."},"is_active":{"type":"boolean","nullable":false,"description":"Inactive types cannot be applied for, but keep their history."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"LeavePolicy":{"type":"object","description":"The entitlement rules for one leave type. Read-only: changing a policy retroactively changes what people are entitled to and what has already accrued, which is a decision for the app rather than an API call.","properties":{"object":{"type":"string","enum":["leave_policy"],"nullable":false,"description":"Always `leave_policy`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"leave_type_id":{"type":"string","nullable":false,"description":"The leave type this policy governs."},"annual_quota":{"type":"string","nullable":false,"description":"Days granted for a full year of service."},"accrual_method":{"type":"string","nullable":false,"description":"How the quota is released. `annual` grants it all at the start of the year; `monthly` releases it as the year passes, which is why a balance cannot be derived from the quota alone."},"allocation_type":{"type":"string","nullable":false,"description":"Whether the entitlement runs per fiscal year or per cycle."},"max_consecutive_days":{"type":"integer","nullable":true,"description":"Longest single stretch allowed. Null when unlimited."},"carry_forward_allowed":{"type":"boolean","nullable":false,"description":"Whether unused days survive into the next year."},"max_carry_forward_days":{"type":"string","nullable":false,"description":"Ceiling on days carried forward."},"encashment_allowed":{"type":"boolean","nullable":false,"description":"Whether unused days can be paid out instead of taken."},"negative_balance_allowed":{"type":"boolean","nullable":false,"description":"Whether an employee may go into deficit."},"max_negative_days":{"type":"string","nullable":false,"description":"How far into deficit, when that is allowed."},"pro_rata_for_joiners":{"type":"boolean","nullable":false,"description":"Whether someone joining mid-year gets a proportion of the quota."},"min_service_months":{"type":"integer","nullable":false,"description":"Months of service before this type may be used."},"applicable_gender":{"type":"string","nullable":false,"description":"Restricts the type where the law or the policy does."},"requires_document_after_days":{"type":"integer","nullable":true,"description":"Length past which supporting evidence is expected. Null when never."},"sandwich_rule":{"type":"boolean","nullable":false,"description":"Whether rest days falling inside a leave span are counted against it."},"effective_from":{"type":"string","format":"date","nullable":false,"description":"First day this policy applies."},"effective_to":{"type":"string","format":"date","nullable":true,"description":"Last day it applies. Null while it is the current policy."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"LeaveGroup":{"type":"object","description":"A named set of policies applied together. An employee belongs to one group, which is what decides the leave types available to them.","properties":{"object":{"type":"string","enum":["leave_group"],"nullable":false,"description":"Always `leave_group`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Group name."},"description":{"type":"string","nullable":true,"description":"What the group is for."},"is_active":{"type":"boolean","nullable":false,"description":"Whether the group is in use."},"is_default":{"type":"boolean","nullable":false,"description":"Applied to employees with no group of their own."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"LeaveBalance":{"type":"object","description":"One employee's standing under one leave type for a fiscal year. `available_days` is the number that matters and the only one that accounts for accrual — do not derive it from the others.","properties":{"object":{"type":"string","enum":["leave_balance"],"nullable":false,"description":"Always `leave_balance`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Identifier of the underlying allocation."},"employee_id":{"type":"string","nullable":false,"description":"The employee this balance belongs to."},"leave_type_id":{"type":"string","nullable":false,"description":"The leave type."},"fiscal_year_id":{"type":"string","nullable":false,"description":"The fiscal year this balance covers."},"entitled_days":{"type":"string","nullable":false,"description":"The year's full entitlement, before accrual is applied."},"accrued_days":{"type":"string","nullable":false,"description":"How much of the entitlement has been released so far. Equal to `entitled_days` under an annual policy; a fraction of it under a monthly one."},"carried_forward_days":{"type":"string","nullable":false,"description":"Days brought in from the previous year."},"used_days":{"type":"string","nullable":false,"description":"Days consumed by approved leave."},"encashed_days":{"type":"string","nullable":false,"description":"Days paid out instead of taken."},"available_days":{"type":"string","nullable":false,"description":"What the employee can actually take: accrued + carried forward − used − encashed. Computed here because a client subtracting the raw columns would over-report every monthly-accrual policy."}}},"LeaveApplication":{"type":"object","description":"A request for leave. Approving one consumes the balance and marks the days on the employee's attendance.","properties":{"object":{"type":"string","enum":["leave_application"],"nullable":false,"description":"Always `leave_application`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee requesting leave."},"leave_type_id":{"type":"string","nullable":false,"description":"The kind of leave requested."},"fiscal_year_id":{"type":"string","nullable":false,"description":"The fiscal year the days are drawn from."},"from_date":{"type":"string","format":"date","nullable":false,"description":"First day of leave."},"to_date":{"type":"string","format":"date","nullable":false,"description":"Last day of leave."},"total_days":{"type":"string","nullable":false,"description":"Days this request consumes. Computed by the workspace from its own rest days, holidays and sandwich rule — not simply the span."},"is_half_day":{"type":"boolean","nullable":false,"description":"Whether the request is for half a day."},"half_day_type":{"type":"string","nullable":true,"description":"Which half, when the request is a half day."},"reason":{"type":"string","nullable":false,"description":"Why the leave is being requested."},"status":{"type":"string","enum":["pending","approved","rejected","cancelled"],"nullable":false,"description":"Where the request stands."},"approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was approved or rejected."},"rejection_reason":{"type":"string","nullable":true,"description":"Why it was rejected."},"cancelled_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was cancelled."},"cancellation_reason":{"type":"string","nullable":true,"description":"Why it was cancelled."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"SalaryComponent":{"type":"object","description":"A line that can appear on a payslip — an earning, a deduction, or an employer contribution. The `contributes_to_*` flags decide which statutory bases it counts toward, which is usually only true of basic pay.","properties":{"object":{"type":"string","enum":["salary_component"],"nullable":false,"description":"Always `salary_component`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"code":{"type":"string","nullable":false,"description":"Short code, unique within the workspace."},"type":{"type":"string","enum":["earning","deduction","employer_contribution"],"nullable":false,"description":"What the line does. `employer_contribution` is an employer-paid cost that is NOT part of employee cash — it does not reduce net pay and does not appear in the employee total."},"category":{"type":"string","nullable":true,"description":"Grouping label."},"calculation_type":{"type":"string","nullable":false,"description":"How the amount is derived: fixed, a percentage, or a formula."},"default_value":{"type":"string","nullable":false,"description":"Amount or percentage used when no override is set."},"is_taxable":{"type":"boolean","nullable":false,"description":"Whether the line counts toward taxable income."},"exemption_mode":{"type":"string","nullable":false,"description":"Partial-exemption treatment. `none` means `is_taxable` alone decides; `pct_of_basic` exempts up to a percentage of basic pay; `flat_cap` exempts up to a fixed amount."},"exemption_value":{"type":"string","nullable":false,"description":"The percentage or cap the exemption mode applies."},"affects_gross":{"type":"boolean","nullable":false,"description":"Whether the line is part of gross pay."},"contributes_to_eobi":{"type":"boolean","nullable":false,"description":"Counts toward the statutory social-security base."},"contributes_to_pf":{"type":"boolean","nullable":false,"description":"Counts toward the provident-fund base."},"contributes_to_overtime":{"type":"boolean","nullable":false,"description":"Counts toward the hourly rate overtime is paid at."},"contributes_to_gratuity":{"type":"boolean","nullable":false,"description":"Counts toward the gratuity accrual base."},"is_mandatory":{"type":"boolean","nullable":false,"description":"Present on every structure."},"is_active":{"type":"boolean","nullable":false,"description":"Whether the line is in use."},"display_order":{"type":"integer","nullable":false,"description":"Position on a payslip."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"SalaryStructure":{"type":"object","description":"A named set of components. An employee is assigned one, and the amounts for their own assignment live on the assignment rather than here.","properties":{"object":{"type":"string","enum":["salary_structure"],"nullable":false,"description":"Always `salary_structure`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Structure name."},"description":{"type":"string","nullable":true,"description":"What it is for."},"is_active":{"type":"boolean","nullable":false,"description":"Whether it is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"SalaryStructureComponent":{"type":"object","description":"One component on one structure, with the default it contributes.","properties":{"object":{"type":"string","enum":["salary_structure_component"],"nullable":false,"description":"Always `salary_structure_component`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"salary_structure_id":{"type":"string","nullable":false,"description":"The structure."},"salary_component_id":{"type":"string","nullable":false,"description":"The component."},"calculation_type":{"type":"string","nullable":true,"description":"Overrides the component's own calculation type."},"default_value":{"type":"string","nullable":true,"description":"Amount or percentage for this structure."},"is_mandatory":{"type":"boolean","nullable":false,"description":"Whether the component cannot be removed from an assignment."},"display_order":{"type":"integer","nullable":false,"description":"Position on a payslip."}}},"SalaryAssignment":{"type":"object","description":"An employee's pay, from a date. Assignments form a history: a raise closes the previous one and opens a new one, so the row with a null `effective_to` is the current package.","properties":{"object":{"type":"string","enum":["salary_assignment"],"nullable":false,"description":"Always `salary_assignment`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"salary_structure_id":{"type":"string","nullable":false,"description":"The structure this package follows."},"gross_salary":{"type":"string","nullable":false,"description":"Monthly gross pay."},"effective_from":{"type":"string","format":"date","nullable":false,"description":"First day this package applies."},"effective_to":{"type":"string","format":"date","nullable":true,"description":"Last day it applies. Null while it is the current package."},"reason":{"type":"string","nullable":true,"description":"Why the package changed."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"PayrollRun":{"type":"object","description":"One month's payroll for the workspace. A run moves draft → approved → locked → disbursed; once locked its entries cannot change.","properties":{"object":{"type":"string","enum":["payroll_run"],"nullable":false,"description":"Always `payroll_run`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"fiscal_year_id":{"type":"string","nullable":false,"description":"The fiscal year this run belongs to."},"month":{"type":"integer","nullable":false,"description":"Calendar month, 1–12."},"year":{"type":"integer","nullable":false,"description":"Calendar year."},"run_date":{"type":"string","format":"date","nullable":false,"description":"The date the run covers."},"total_employees":{"type":"integer","nullable":false,"description":"Employees included."},"total_gross":{"type":"string","nullable":false,"description":"Sum of gross pay across the run."},"total_deductions":{"type":"string","nullable":false,"description":"Sum of deductions."},"total_net":{"type":"string","nullable":false,"description":"Sum of net pay — what is actually disbursed."},"total_employer_cost":{"type":"string","nullable":false,"description":"Employer-paid contributions on top of net pay. Not part of what employees receive."},"status":{"type":"string","enum":["draft","processed","approved","locked","disbursed"],"nullable":false,"description":"Where the run stands."},"source":{"type":"string","enum":["processed","imported"],"nullable":false,"description":"`processed` came from the monthly pipeline. `imported` was backfilled from a historical file — it has no attendance behind it, so its per-day figures are zero rather than measured."},"approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the run was approved."},"locked_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was locked and became immutable."},"disbursed_at":{"type":"string","format":"date-time","nullable":true,"description":"When payment was recorded."},"notes":{"type":"string","nullable":true,"description":"Free-text note."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"PayrollEntry":{"type":"object","description":"One employee's pay for one run. The attendance figures are what the calculation actually used, so they explain the deductions rather than merely accompanying them.","properties":{"object":{"type":"string","enum":["payroll_entry"],"nullable":false,"description":"Always `payroll_entry`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"payroll_run_id":{"type":"string","nullable":false,"description":"The run this entry belongs to."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"salary_assignment_id":{"type":"string","nullable":false,"description":"The pay package the calculation used."},"working_days":{"type":"string","nullable":false,"description":"Days in the month the employee was expected to work."},"present_days":{"type":"string","nullable":false,"description":"Days counted as present."},"absent_days":{"type":"string","nullable":false,"description":"Days counted as absent."},"leave_days":{"type":"string","nullable":false,"description":"Days on approved leave."},"unpaid_leave_days":{"type":"string","nullable":false,"description":"Leave days that are not paid."},"half_days":{"type":"string","nullable":false,"description":"Days counted as half."},"late_count":{"type":"integer","nullable":false,"description":"Late arrivals."},"early_leave_count":{"type":"integer","nullable":false,"description":"Early departures."},"holidays":{"type":"integer","nullable":false,"description":"Public holidays in the month."},"overtime_hours":{"type":"string","nullable":false,"description":"Approved overtime hours paid."},"gross_salary":{"type":"string","nullable":false,"description":"Gross pay before deductions."},"total_earnings":{"type":"string","nullable":false,"description":"Earnings including bonus and additions."},"total_deductions":{"type":"string","nullable":false,"description":"Everything subtracted."},"net_salary":{"type":"string","nullable":false,"description":"What the employee is paid."},"employer_contributions":{"type":"string","nullable":false,"description":"Employer-paid contributions. On top of net pay, not deducted from it."},"taxable_income":{"type":"string","nullable":false,"description":"The base income tax was computed on."},"tax_amount":{"type":"string","nullable":false,"description":"Income tax withheld."},"loan_deduction":{"type":"string","nullable":false,"description":"Loan installments claimed this month."},"absence_deduction":{"type":"string","nullable":false,"description":"Deducted for absent days."},"unpaid_leave_deduction":{"type":"string","nullable":false,"description":"Deducted for unpaid leave. Separate from absence so the two reconcile distinctly on a slip."},"late_deduction":{"type":"string","nullable":false,"description":"Deducted for lateness."},"bonus_amount":{"type":"string","nullable":false,"description":"Approved bonuses added this month."},"adjustment_addition":{"type":"string","nullable":false,"description":"Approved one-off additions."},"adjustment_deduction":{"type":"string","nullable":false,"description":"Approved one-off deductions."},"payment_method":{"type":"string","nullable":false,"description":"How the salary is paid."},"payment_date":{"type":"string","format":"date","nullable":true,"description":"The date the transfer was actually made."},"payment_reference":{"type":"string","nullable":true,"description":"Transfer or cheque reference."},"paid_at":{"type":"string","format":"date-time","nullable":true,"description":"When the entry was marked paid in the system."},"acknowledged_at":{"type":"string","format":"date-time","nullable":true,"description":"When the employee confirmed receipt."},"status":{"type":"string","nullable":false,"description":"Where the entry stands."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"PayrollEntryComponent":{"type":"object","description":"One line on one payslip, with the amount actually applied. This is what turns an entry total into an explanation.","properties":{"object":{"type":"string","enum":["payroll_entry_component"],"nullable":false,"description":"Always `payroll_entry_component`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"payroll_entry_id":{"type":"string","nullable":false,"description":"The entry this line belongs to."},"salary_component_id":{"type":"string","nullable":false,"description":"The component."},"type":{"type":"string","enum":["earning","deduction","employer_contribution"],"nullable":false,"description":"Earning, deduction, or employer contribution."},"amount":{"type":"string","nullable":false,"description":"The amount applied."},"is_taxable":{"type":"boolean","nullable":false,"description":"Whether it counted toward taxable income."},"display_order":{"type":"integer","nullable":false,"description":"Position on the payslip."}}},"SalarySlip":{"type":"object","description":"A rendered payslip document. The PDF itself is not exposed — the file lives in workspace storage and is delivered by email or the portal.","properties":{"object":{"type":"string","enum":["salary_slip"],"nullable":false,"description":"Always `salary_slip`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"payroll_entry_id":{"type":"string","nullable":false,"description":"The entry this slip renders."},"slip_number":{"type":"string","nullable":true,"description":"Human-facing reference."},"language":{"type":"string","nullable":true,"description":"Language the slip was generated in. Null means English."},"emailed_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was emailed to the employee."},"generated_at":{"type":"string","format":"date-time","nullable":false,"description":"When it was rendered."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."}}},"LoanType":{"type":"object","description":"A kind of loan the workspace offers, with its limits.","properties":{"object":{"type":"string","enum":["loan_type"],"nullable":false,"description":"Always `loan_type`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"code":{"type":"string","nullable":false,"description":"Short code, unique within the workspace."},"max_amount":{"type":"string","nullable":true,"description":"Largest loan of this kind. Null when unlimited."},"max_installments":{"type":"integer","nullable":true,"description":"Longest repayment. Null when unlimited."},"interest_rate":{"type":"string","nullable":false,"description":"Annual rate, as a percentage."},"max_active_loans":{"type":"integer","nullable":false,"description":"How many of this kind an employee may hold at once."},"is_active":{"type":"boolean","nullable":false,"description":"Whether it is offered."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Loan":{"type":"object","description":"A loan to an employee. Installments are claimed against payroll as the months come round, so `outstanding_balance` moves with each run.","properties":{"object":{"type":"string","enum":["loan"],"nullable":false,"description":"Always `loan`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"loan_type_id":{"type":"string","nullable":false,"description":"The kind of loan."},"loan_number":{"type":"string","nullable":true,"description":"Human-facing reference."},"amount":{"type":"string","nullable":false,"description":"Principal advanced."},"interest_rate":{"type":"string","nullable":false,"description":"Annual rate, as a percentage."},"total_payable":{"type":"string","nullable":false,"description":"Principal plus interest."},"installment_amount":{"type":"string","nullable":false,"description":"Amount due each month."},"total_installments":{"type":"integer","nullable":false,"description":"Months of repayment."},"paid_installments":{"type":"integer","nullable":false,"description":"Installments settled so far."},"paid_amount":{"type":"string","nullable":false,"description":"Repaid so far."},"outstanding_balance":{"type":"string","nullable":false,"description":"Still owed."},"start_month":{"type":"integer","nullable":false,"description":"First repayment month, 1–12."},"start_year":{"type":"integer","nullable":false,"description":"First repayment year."},"purpose":{"type":"string","nullable":true,"description":"Why the loan was taken."},"status":{"type":"string","nullable":false,"description":"Where the loan stands."},"approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was approved."},"completed_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was fully repaid."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"LoanInstallment":{"type":"object","description":"One scheduled repayment. Claimed when the payroll run for its due month is processed, and settled when that run is locked.","properties":{"object":{"type":"string","enum":["loan_installment"],"nullable":false,"description":"Always `loan_installment`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"loan_id":{"type":"string","nullable":false,"description":"The loan."},"installment_no":{"type":"integer","nullable":false,"description":"Position in the schedule, from 1."},"due_month":{"type":"integer","nullable":false,"description":"Month due, 1–12."},"due_year":{"type":"integer","nullable":false,"description":"Year due."},"principal":{"type":"string","nullable":false,"description":"Principal portion."},"interest":{"type":"string","nullable":false,"description":"Interest portion."},"total_due":{"type":"string","nullable":false,"description":"Total for this installment."},"paid_amount":{"type":"string","nullable":false,"description":"Amount actually settled."},"status":{"type":"string","nullable":false,"description":"Where the installment stands."},"paid_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was settled."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"ExpenseCategory":{"type":"object","description":"A kind of expense that can be claimed.","properties":{"object":{"type":"string","enum":["expense_category"],"nullable":false,"description":"Always `expense_category`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"description":{"type":"string","nullable":true,"description":"What belongs in it."},"is_active":{"type":"boolean","nullable":false,"description":"Whether it can be claimed against."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"ExpenseClaim":{"type":"object","description":"A reimbursement request. Two levels of approval, and an approved claim becomes a payroll addition rather than a separate payment.","properties":{"object":{"type":"string","enum":["expense_claim"],"nullable":false,"description":"Always `expense_claim`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"title":{"type":"string","nullable":false,"description":"What the claim is for."},"description":{"type":"string","nullable":true,"description":"Detail."},"total_amount":{"type":"string","nullable":false,"description":"Sum of the claim items."},"status":{"type":"string","enum":["draft","submitted","manager_approved","approved","rejected","cancelled","paid"],"nullable":false,"description":"Where the claim stands."},"submitted_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was submitted."},"manager_approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the manager approved it."},"hr_approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When HR gave final approval."},"rejected_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was rejected."},"rejection_reason":{"type":"string","nullable":true,"description":"Why it was rejected."},"cancelled_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was withdrawn."},"payroll_adjustment_id":{"type":"string","nullable":true,"description":"The payroll addition an approved claim created."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"ExpenseClaimItem":{"type":"object","description":"One line on a claim. Receipts are not exposed.","properties":{"object":{"type":"string","enum":["expense_claim_item"],"nullable":false,"description":"Always `expense_claim_item`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"claim_id":{"type":"string","nullable":false,"description":"The claim."},"category_id":{"type":"string","nullable":false,"description":"The expense category."},"expense_date":{"type":"string","format":"date","nullable":false,"description":"When the expense was incurred."},"amount":{"type":"string","nullable":false,"description":"The amount claimed."},"description":{"type":"string","nullable":true,"description":"What it was for."},"sort_order":{"type":"integer","nullable":false,"description":"Position on the claim."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"DocumentType":{"type":"object","description":"A kind of document the workspace collects — a passport, a degree, a contract copy. Mandatory types are the ones an employee record is considered incomplete without.","properties":{"object":{"type":"string","enum":["document_type"],"nullable":false,"description":"Always `document_type`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"code":{"type":"string","nullable":true,"description":"Short code."},"is_mandatory":{"type":"boolean","nullable":false,"description":"Whether every employee is expected to have one."},"allowed_formats":{"type":"string","nullable":false,"description":"File types accepted, as a comma-separated list."},"max_file_size_mb":{"type":"integer","nullable":false,"description":"Largest upload accepted, in megabytes."},"allow_multiple_entries":{"type":"boolean","nullable":true,"description":"Whether an employee may hold several of this type."},"sort_order":{"type":"integer","nullable":true,"description":"Display position."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"EmployeeDocument":{"type":"object","description":"One document held against an employee. The file itself is not exposed — only whether it exists, and whether someone has verified it.","properties":{"object":{"type":"string","enum":["employee_document"],"nullable":false,"description":"Always `employee_document`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"document_type_id":{"type":"string","nullable":false,"description":"The kind of document."},"entry_label":{"type":"string","nullable":true,"description":"Label distinguishing several documents of one type."},"verification_status":{"type":"string","enum":["pending","verified","rejected"],"nullable":false,"description":"Whether the document has been checked."},"verified_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was verified."},"rejection_reason":{"type":"string","nullable":true,"description":"Why it was rejected."},"version":{"type":"integer","nullable":false,"description":"Increments when the document is replaced."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Contract":{"type":"object","description":"An employment contract. Signing one is what activates an employee, so `status` here and an employee’s status move together.","properties":{"object":{"type":"string","enum":["contract"],"nullable":false,"description":"Always `contract`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"contract_number":{"type":"string","nullable":true,"description":"Human-facing reference."},"type":{"type":"string","nullable":false,"description":"The kind of contract."},"start_date":{"type":"string","format":"date","nullable":false,"description":"First day of the term."},"end_date":{"type":"string","format":"date","nullable":true,"description":"Last day. Null for an open-ended contract."},"probation_months":{"type":"integer","nullable":false,"description":"Length of probation."},"salary_structure_id":{"type":"string","nullable":true,"description":"Structure the contract sets."},"gross_salary":{"type":"string","nullable":true,"description":"Gross pay the contract sets."},"status":{"type":"string","nullable":false,"description":"Where the contract stands."},"signed_date":{"type":"string","format":"date","nullable":true,"description":"When it was signed."},"accepted_electronically":{"type":"boolean","nullable":false,"description":"Whether it was accepted through the portal rather than on paper."},"accepted_at":{"type":"string","format":"date-time","nullable":true,"description":"When the employee accepted it."},"language":{"type":"string","nullable":true,"description":"Language it was issued in. Null means English."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"HrLetter":{"type":"object","description":"A letter issued to an employee — an employment certificate, a salary letter, an experience letter. The rendered PDF is not exposed.","properties":{"object":{"type":"string","enum":["hr_letter"],"nullable":false,"description":"Always `hr_letter`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"letter_type":{"type":"string","nullable":false,"description":"The kind of letter."},"reference_number":{"type":"string","nullable":false,"description":"Human-facing reference, printed on the letter."},"language":{"type":"string","nullable":true,"description":"Language it was issued in. Null means English."},"issued_date":{"type":"string","format":"date","nullable":false,"description":"The date on the letter."},"emailed_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was emailed to the employee."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."}}},"HrLetterRequest":{"type":"object","description":"An employee asking for a letter. An approved request produces an issued letter, which `issued_letter_id` points at.","properties":{"object":{"type":"string","enum":["hr_letter_request"],"nullable":false,"description":"Always `hr_letter_request`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"letter_type":{"type":"string","nullable":false,"description":"The kind requested."},"purpose":{"type":"string","nullable":false,"description":"Why it is needed."},"addressed_to":{"type":"string","nullable":true,"description":"Who the letter should be addressed to."},"status":{"type":"string","nullable":false,"description":"Where the request stands."},"rejection_reason":{"type":"string","nullable":true,"description":"Why it was refused."},"decided_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was decided."},"issued_letter_id":{"type":"string","nullable":true,"description":"The letter this request produced."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AssetCategory":{"type":"object","description":"A kind of company asset — laptops, phones, vehicles.","properties":{"object":{"type":"string","enum":["asset_category"],"nullable":false,"description":"Always `asset_category`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"description":{"type":"string","nullable":true,"description":"What belongs in it."},"is_active":{"type":"boolean","nullable":false,"description":"Whether it is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Asset":{"type":"object","description":"One piece of company property. `current_assignment_id` points at who holds it now, and is null when it is back in stock.","properties":{"object":{"type":"string","enum":["asset"],"nullable":false,"description":"Always `asset`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"category_id":{"type":"string","nullable":false,"description":"The kind of asset."},"asset_tag":{"type":"string","nullable":false,"description":"The workspace’s own tag, unique within it."},"name":{"type":"string","nullable":false,"description":"What it is."},"serial_number":{"type":"string","nullable":true,"description":"Manufacturer's serial."},"purchase_date":{"type":"string","format":"date","nullable":true,"description":"When it was bought."},"purchase_cost":{"type":"string","nullable":true,"description":"What it cost."},"warranty_expiry":{"type":"string","format":"date","nullable":true,"description":"When the warranty runs out."},"vendor":{"type":"string","nullable":true,"description":"Who supplied it."},"condition":{"type":"string","nullable":false,"description":"Physical condition."},"status":{"type":"string","nullable":false,"description":"Whether it is issued, in stock, or retired."},"current_assignment_id":{"type":"string","nullable":true,"description":"The assignment holding it now. Null when unassigned."},"notes":{"type":"string","nullable":true,"description":"Free-text note."},"deleted":{"type":"boolean","nullable":false,"description":"True for a retired asset. Hidden by default; pass `include_deleted` to see them, which a client mirroring assets needs in order to observe a removal at all."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AssetAssignment":{"type":"object","description":"One issue-and-return cycle. A returned assignment is kept, so the history of who held what survives the return.","properties":{"object":{"type":"string","enum":["asset_assignment"],"nullable":false,"description":"Always `asset_assignment`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"asset_id":{"type":"string","nullable":false,"description":"The asset."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"issued_at":{"type":"string","format":"date-time","nullable":false,"description":"When it was handed over."},"issued_condition":{"type":"string","nullable":true,"description":"Condition at issue."},"issued_notes":{"type":"string","nullable":true,"description":"Note taken at issue."},"expected_return_date":{"type":"string","format":"date","nullable":true,"description":"When it is due back."},"returned_at":{"type":"string","format":"date-time","nullable":true,"description":"When it came back. Null while still held."},"returned_condition":{"type":"string","nullable":true,"description":"Condition on return."},"returned_notes":{"type":"string","nullable":true,"description":"Note taken on return."},"status":{"type":"string","nullable":false,"description":"Whether the assignment is open or closed."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"JobOpening":{"type":"object","description":"A role the workspace is hiring for.","properties":{"object":{"type":"string","enum":["job_opening"],"nullable":false,"description":"Always `job_opening`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"title":{"type":"string","nullable":false,"description":"Job title."},"department_id":{"type":"string","nullable":true,"description":"Department the role sits in."},"designation_id":{"type":"string","nullable":true,"description":"Designation the role maps to."},"branch_id":{"type":"string","nullable":true,"description":"Branch the role is based at."},"employment_type_id":{"type":"string","nullable":true,"description":"Employment type offered."},"level":{"type":"integer","nullable":true,"description":"Seniority level."},"headcount":{"type":"integer","nullable":false,"description":"How many people are being hired."},"status":{"type":"string","nullable":false,"description":"Where the opening stands."},"budget_approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the headcount was signed off."},"closed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the opening was closed."},"notes":{"type":"string","nullable":true,"description":"Free-text note."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Candidate":{"type":"object","description":"Someone who has applied. These are people outside the workspace, so the record carries personal contact details and sits behind its own `recruitment:read` scope. The CV file is not exposed.","properties":{"object":{"type":"string","enum":["candidate"],"nullable":false,"description":"Always `candidate`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"first_name":{"type":"string","nullable":false,"description":"Given name."},"last_name":{"type":"string","nullable":false,"description":"Family name."},"email":{"type":"string","nullable":false,"description":"Contact email."},"phone":{"type":"string","nullable":true,"description":"Contact phone."},"current_employer":{"type":"string","nullable":true,"description":"Where they work now."},"current_designation":{"type":"string","nullable":true,"description":"Their current job title."},"linkedin_url":{"type":"string","nullable":true,"description":"Their LinkedIn profile."},"notes":{"type":"string","nullable":true,"description":"Free-text note."},"converted_employee_id":{"type":"string","nullable":true,"description":"The employee record created when they were hired."},"converted_at":{"type":"string","format":"date-time","nullable":true,"description":"When they became an employee."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"Application":{"type":"object","description":"One candidate against one opening, and where they are in the process.","properties":{"object":{"type":"string","enum":["application"],"nullable":false,"description":"Always `application`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"candidate_id":{"type":"string","nullable":false,"description":"The candidate."},"job_opening_id":{"type":"string","nullable":false,"description":"The opening applied for."},"stage":{"type":"string","nullable":false,"description":"Where they are in the pipeline."},"source":{"type":"string","nullable":false,"description":"How they arrived."},"source_detail":{"type":"string","nullable":true,"description":"More about the source."},"applied_at":{"type":"string","format":"date-time","nullable":false,"description":"When they applied."},"screened_at":{"type":"string","format":"date-time","nullable":true,"description":"When they were screened."},"rejected_at":{"type":"string","format":"date-time","nullable":true,"description":"When they were rejected."},"rejection_reason":{"type":"string","nullable":true,"description":"Why they were rejected."},"withdrawn_at":{"type":"string","format":"date-time","nullable":true,"description":"When they withdrew."},"hired_at":{"type":"string","format":"date-time","nullable":true,"description":"When they were hired."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AnnouncementCategory":{"type":"object","description":"A grouping for announcements.","properties":{"object":{"type":"string","enum":["announcement_category"],"nullable":false,"description":"Always `announcement_category`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Display name."},"color":{"type":"string","nullable":false,"description":"Hex colour used to render it."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."}}},"Announcement":{"type":"object","description":"A notice to the workspace. Who it reaches is decided by `target_type` and an audience the API does not expose; the attachment is not exposed either.","properties":{"object":{"type":"string","enum":["announcement"],"nullable":false,"description":"Always `announcement`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"category_id":{"type":"string","nullable":true,"description":"The category it belongs to."},"title":{"type":"string","nullable":false,"description":"Headline."},"body":{"type":"string","nullable":false,"description":"The announcement text."},"priority":{"type":"string","nullable":false,"description":"How prominently it is shown."},"target_type":{"type":"string","nullable":false,"description":"Whether it goes to everyone or to a selected audience."},"is_pinned":{"type":"boolean","nullable":false,"description":"Whether it stays at the top."},"publish_at":{"type":"string","format":"date-time","nullable":true,"description":"When it becomes visible."},"expires_at":{"type":"string","format":"date-time","nullable":true,"description":"When it stops being shown."},"send_email":{"type":"boolean","nullable":false,"description":"Whether it was also emailed."},"status":{"type":"string","nullable":false,"description":"Draft, published, or archived."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AttendanceRecord":{"type":"object","description":"One employee's attendance for one calendar day. There is at most one per (employee, date), so writing the same day twice replaces it rather than adding a second record.","properties":{"object":{"type":"string","enum":["attendance_record"],"nullable":false,"description":"Always `attendance_record`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"date":{"type":"string","format":"date","nullable":false,"description":"The calendar day, in the workspace timezone. An overnight shift is attributed to the day it started."},"status":{"type":"string","enum":["present","late","early_leave","absent","half_day","on_leave","holiday","weekend","work_from_home","compensatory_off","not_marked"],"nullable":false,"description":"How the day is counted for pay."},"clock_in":{"type":"string","format":"date-time","nullable":true,"description":"First punch of the day."},"clock_out":{"type":"string","format":"date-time","nullable":true,"description":"Last punch inside the valid checkout window."},"late_minutes":{"type":"integer","nullable":false,"description":"Minutes past the shift start, after the grace period."},"early_leaving_minutes":{"type":"integer","nullable":false,"description":"Minutes the employee left before the shift ended."},"overtime_minutes":{"type":"integer","nullable":false,"description":"Overtime credited for the day. Zero while an overtime request is still pending, in a workspace that requires approval."},"working_hours":{"type":"string","nullable":false,"description":"Hours worked, net of the shift's unpaid break."},"shift_id":{"type":"string","nullable":true,"description":"Shift in effect on this date."},"source":{"type":"string","enum":["manual","auto","regularization","biometric","geo","api"],"nullable":false,"description":"What wrote the row. `manual` covers deliberate marks including this API's, `auto` the auto-present job, `regularization` an approved correction, and `biometric` / `geo` / `api` a punch of that origin."},"is_manual_override":{"type":"boolean","nullable":false,"description":"When true the status is pinned and the late-threshold recompute will not change it, however the punches land."},"remarks":{"type":"string","nullable":true,"description":"Free-text note."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AttendancePunch":{"type":"object","description":"A single clock-in or clock-out event. Punches are an append-only log: every punch is kept, including ones that changed no attendance record.","properties":{"object":{"type":"string","enum":["attendance_punch"],"nullable":false,"description":"Always `attendance_punch`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"punch_time":{"type":"string","format":"date-time","nullable":false,"description":"When the punch happened."},"punch_type":{"type":"string","enum":["in","out"],"nullable":false,"description":"Direction of the punch."},"source":{"type":"string","nullable":false,"description":"Where the punch came from. API-recorded punches are `api`."},"device_id":{"type":"string","nullable":true,"description":"Identifier of the device that captured the punch."},"ip_address":{"type":"string","nullable":true,"description":"Address the punch was submitted from."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."}}},"AttendanceRegularization":{"type":"object","description":"A request to correct one day's attendance. Approving one overwrites the attendance record for that date and marks it as coming from a regularisation, which protects it from later automatic recomputation.","properties":{"object":{"type":"string","enum":["attendance_regularization"],"nullable":false,"description":"Always `attendance_regularization`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"date":{"type":"string","format":"date","nullable":false,"description":"The day being corrected."},"requested_status":{"type":"string","enum":["present","late","early_leave","absent","half_day","on_leave","holiday","weekend","work_from_home","compensatory_off","not_marked"],"nullable":false,"description":"Status the employee is asking for."},"clock_in":{"type":"string","format":"date-time","nullable":true,"description":"Corrected clock-in."},"clock_out":{"type":"string","format":"date-time","nullable":true,"description":"Corrected clock-out."},"previous_status":{"type":"string","nullable":true,"description":"What the day looked like at the moment of the decision. Null while the request is pending — the record it would replace can still change."},"previous_clock_in":{"type":"string","format":"date-time","nullable":true,"description":"Clock-in before the decision."},"previous_clock_out":{"type":"string","format":"date-time","nullable":true,"description":"Clock-out before the decision."},"reason":{"type":"string","nullable":false,"description":"Why the correction is being asked for."},"status":{"type":"string","enum":["pending","approved","rejected"],"nullable":false,"description":"Where the request stands."},"approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was approved or rejected."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"OvertimeRequest":{"type":"object","description":"A claim for overtime on one day. Whether overtime counts toward pay without one depends on the workspace's attendance settings.","properties":{"object":{"type":"string","enum":["overtime_request"],"nullable":false,"description":"Always `overtime_request`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"date":{"type":"string","format":"date","nullable":false,"description":"The day the overtime was worked."},"hours":{"type":"string","nullable":false,"description":"Hours claimed."},"reason":{"type":"string","nullable":true,"description":"Justification."},"status":{"type":"string","enum":["pending","approved","rejected"],"nullable":false,"description":"Where the request stands. A workspace with auto-approval on returns `approved` straight from the create call."},"approved_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was approved or rejected."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"RestDaySwap":{"type":"object","description":"An employee works one of their rest days and takes a different day off instead. `worked_date` becomes an ordinary working day and `off_date` becomes the rest day, for both the calendar and payroll.","properties":{"object":{"type":"string","enum":["rest_day_swap"],"nullable":false,"description":"Always `rest_day_swap`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"worked_date":{"type":"string","format":"date","nullable":false,"description":"The rest day that was worked."},"off_date":{"type":"string","format":"date","nullable":false,"description":"The working day taken off in exchange."},"reason":{"type":"string","nullable":true,"description":"Free-text note."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"EmployeeShift":{"type":"object","description":"Which shift an employee works, from a given date. Assignments form a history: creating one closes the previous open assignment the day before the new one starts.","properties":{"object":{"type":"string","enum":["employee_shift"],"nullable":false,"description":"Always `employee_shift`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"employee_id":{"type":"string","nullable":false,"description":"The employee this record belongs to."},"shift_id":{"type":"string","nullable":false,"description":"The shift being worked."},"effective_from":{"type":"string","format":"date","nullable":false,"description":"First day this assignment applies."},"effective_to":{"type":"string","format":"date","nullable":true,"description":"Last day it applies. Null while it is the current assignment."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."}}},"AttendanceSite":{"type":"object","description":"A geofenced location employees may clock in from. Only meaningful when geo attendance is enabled for the workspace.","properties":{"object":{"type":"string","enum":["attendance_site"],"nullable":false,"description":"Always `attendance_site`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"name":{"type":"string","nullable":false,"description":"Site name."},"latitude":{"type":"string","nullable":false,"description":"Centre of the geofence, in decimal degrees."},"longitude":{"type":"string","nullable":false,"description":"Centre of the geofence, in decimal degrees."},"radius_meters":{"type":"integer","nullable":false,"description":"How far from the centre a punch is accepted."},"branch_id":{"type":"string","nullable":true,"description":"Branch this site belongs to."},"status":{"type":"string","enum":["active","inactive"],"nullable":false,"description":"Whether the site is in use."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}},"AttendanceSettings":{"type":"object","description":"How the workspace grades attendance. Read-only here, and published because without it the minutes and statuses on an attendance record cannot be interpreted — a `late_minutes` of 20 means nothing until you know the grace period was 15.","properties":{"object":{"type":"string","enum":["attendance_settings"],"nullable":false,"description":"Always `attendance_settings`. Every object names its own type, so a payload stays self-describing after it has been passed through your code."},"id":{"type":"string","nullable":false,"description":"Unique identifier."},"grace_period_minutes":{"type":"integer","nullable":false,"description":"Lateness forgiven entirely. A shift may carry its own grace period, which wins wherever it is set."},"late_threshold_1_minutes":{"type":"integer","nullable":false,"description":"Minutes late at which the first action applies."},"late_threshold_1_action":{"type":"string","nullable":false,"description":"What happens at the first threshold."},"late_threshold_2_minutes":{"type":"integer","nullable":false,"description":"Minutes late at which the second action applies."},"late_threshold_2_action":{"type":"string","nullable":false,"description":"What happens at the second threshold."},"late_threshold_3_minutes":{"type":"integer","nullable":false,"description":"Minutes late at which the third action applies."},"late_threshold_3_action":{"type":"string","nullable":false,"description":"What happens at the third threshold."},"lates_per_month_for_absent":{"type":"integer","nullable":false,"description":"How many late days in a month count as one absence."},"overtime_min_minutes":{"type":"integer","nullable":false,"description":"Shortest stretch past the shift end that counts as overtime."},"overtime_rate_multiplier":{"type":"string","nullable":false,"description":"Multiple of the ordinary hourly rate paid for overtime."},"overtime_require_approval":{"type":"boolean","nullable":false,"description":"When true, overtime minutes only count once a request is approved."},"overtime_auto_approve":{"type":"boolean","nullable":false,"description":"When true, overtime requests are approved on creation."},"checkout_grace_minutes":{"type":"integer","nullable":false,"description":"How long after the shift end a clock-out is still accepted onto the day."},"working_days_per_week":{"type":"integer","nullable":false,"description":"Working days in a normal week."},"week_off_days":{"type":"string","nullable":false,"description":"Default weekly rest days, where a shift does not set its own."},"geo_attendance_enabled":{"type":"boolean","nullable":false,"description":"Whether punches are geofenced to assigned sites."},"geo_max_accuracy_meters":{"type":"integer","nullable":false,"description":"Worst GPS accuracy accepted. A coarser fix is refused rather than trusted, since it could place someone inside a fence they are nowhere near."},"created_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record was created."},"updated_at":{"type":"string","format":"date-time","nullable":false,"description":"When the record last changed."}}}},"parameters":{"Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Page size. Values above 100 are clamped."},"StartingAfter":{"name":"starting_after","in":"query","schema":{"type":"string"},"description":"Opaque cursor from a previous response’s `next_cursor`."},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":255},"description":"A unique value per logical request. Replaying it returns the original response with `Idempotent-Replay: true`."},"ResourceId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The identifier returned as `id` on the object."},"UpdatedSince":{"name":"updated_since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Return records changed at or after this instant. Tracks the record itself, not its child collections."}}},"paths":{"/v1/me":{"get":{"summary":"Describe the calling API key","description":"Identity and scopes of the key making the request.","responses":{"200":{"description":"The key."},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/company":{"get":{"summary":"Retrieve the workspace","description":"Currency and timezone are published here because every money and date field elsewhere is expressed in them.","responses":{"200":{"description":"The workspace."},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employees":{"get":{"summary":"List employees","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","description":"Only employees with this employment status.","schema":{"type":"string","enum":["new","active","inactive","terminated","resigned","retired"]}},{"name":"department_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only employees in this department."},{"name":"employee_code","in":"query","schema":{"type":"string"},"description":"Look up one employee by the code the workspace assigned."},{"name":"include_deleted","in":"query","schema":{"type":"boolean","default":false},"description":"Include soft-deleted employees, flagged `deleted: true`. Required for a client syncing on `updated_since` to observe removals."}],"responses":{"200":{"description":"A page of employees.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Employee"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an employee","description":"Supports `Idempotency-Key`, which is strongly recommended: without it a timed-out retry creates a second employee. Portal access is never granted by this endpoint, so importing staff sends no email.\n\n`employee_code` is not accepted — the workspace assigns it from its own numbering settings and returns it on the created record.","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":255},"description":"A unique value per logical request. Replaying it returns the original response with `Idempotent-Replay: true`."}],"responses":{"201":{"description":"The created employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The employee code is already in use, or the idempotency key was reused with a different body.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/departments":{"get":{"summary":"List departments","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive"]},"description":"Only records in this state."}],"responses":{"200":{"description":"A page of departments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Department"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a department","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created department.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Department"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/departments/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a department","responses":{"200":{"description":"The department.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Department"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such department in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a department","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated department.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Department"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such department in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a department","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted department.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Department"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such department in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/designations":{"get":{"summary":"List designations","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive"]},"description":"Only records in this state."}],"responses":{"200":{"description":"A page of designations.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Designation"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a designation","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created designation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Designation"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/designations/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a designation","responses":{"200":{"description":"The designation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Designation"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such designation in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a designation","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated designation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Designation"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such designation in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a designation","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted designation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Designation"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such designation in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/branches":{"get":{"summary":"List branches","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive"]},"description":"Only records in this state."}],"responses":{"200":{"description":"A page of branches.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a branch","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Branch"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/branches/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a branch","responses":{"200":{"description":"The branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Branch"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such branch in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a branch","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Branch"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such branch in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a branch","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Branch"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such branch in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employment_types":{"get":{"summary":"List employment types","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"}],"responses":{"200":{"description":"A page of employment types.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmploymentType"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a employment type","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created employment type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmploymentType"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employment_types/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a employment type","responses":{"200":{"description":"The employment type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmploymentType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employment type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a employment type","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated employment type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmploymentType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employment type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a employment type","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted employment type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmploymentType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employment type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/pay_grades":{"get":{"summary":"List pay grades","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"}],"responses":{"200":{"description":"A page of pay grades.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PayGrade"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a pay grade","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created pay grade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayGrade"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/pay_grades/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a pay grade","responses":{"200":{"description":"The pay grade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayGrade"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such pay grade in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a pay grade","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated pay grade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayGrade"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such pay grade in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a pay grade","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted pay grade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayGrade"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such pay grade in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/shifts":{"get":{"summary":"List shifts","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive"]},"description":"Only records in this state."}],"responses":{"200":{"description":"A page of shifts.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Shift"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a shift","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shift"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/shifts/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a shift","responses":{"200":{"description":"The shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shift"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such shift in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a shift","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shift"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such shift in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a shift","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shift"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such shift in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/holidays":{"get":{"summary":"List holidays","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"year","in":"query","schema":{"type":"integer"},"description":"Only holidays in this calendar year."},{"name":"branch_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only holidays observed at this branch."}],"responses":{"200":{"description":"A page of holidays.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Holiday"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a holiday","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The created holiday.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Holiday"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A conflicting record exists, or a referenced id does not.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/holidays/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a holiday","responses":{"200":{"description":"The holiday.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Holiday"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such holiday in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a holiday","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated holiday.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Holiday"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such holiday in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a holiday","description":"Permanent — these records have no soft-delete state. Refused with 409 while anything still references the record.","responses":{"200":{"description":"The deleted holiday.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Holiday"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such holiday in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The record is still referenced by other records.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_records":{"get":{"summary":"List attendance records","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the record's own date."},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."},{"name":"status","in":"query","schema":{"type":"string","enum":["present","late","early_leave","absent","half_day","on_leave","holiday","weekend","work_from_home","compensatory_off","not_marked"]},"description":"Only days with this status."}],"responses":{"200":{"description":"A page of attendance records.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttendanceRecord"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Mark attendance","description":"Marks one day for one employee. There is at most one record per (employee, date), so this REPLACES an existing day rather than adding a second one — which is why it answers 200 and not 201.\n\nUnless `is_manual_override` is set, a status the punches contradict is re-graded by the workspace's own late thresholds: sending `present` for a day with a two-hour late clock-in can come back as `absent`. That is usually what you want, and occasionally the opposite.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The resulting attendance record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRecord"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The request conflicts with the current state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_records/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an attendance record","responses":{"200":{"description":"The attendance record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRecord"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance record in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_punches":{"get":{"summary":"List attendance punches","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"punch_type","in":"query","schema":{"type":"string","enum":["in","out"]},"description":"Only clock-ins, or only clock-outs."},{"name":"punched_after","in":"query","schema":{"type":"string","format":"date-time"},"description":"Inclusive lower bound on `punch_time`."},{"name":"punched_before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Exclusive upper bound on `punch_time`."}],"responses":{"200":{"description":"A page of attendance punches.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttendancePunch"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an attendance punch","description":"Records a punch and applies it to the day, exactly as a device punch is applied — attribution date, lateness grading and the checkout window all behave identically.\n\n`punch_time` may be backdated, since a time clock that lost connectivity has to be able to push what it buffered. It may not be post-dated.\n\nA punch that changes no attendance record answers **409**, not 201: a clock-in when the employee is already clocked in, a clock-out with no open record, or a clock-out past the checkout window. The punch is still written to the log in every one of those cases, so a 409 here means \"the punch was kept but the day did not move\", never \"nothing happened\".","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting attendance punch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendancePunch"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The punch was recorded in the log but changed no attendance record. `detail` says which case applied.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_punches/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an attendance punch","responses":{"200":{"description":"The attendance punch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendancePunch"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance punch in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_regularizations":{"get":{"summary":"List attendance regularizations","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected"]},"description":"Only requests in this state."},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the record's own date."},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."}],"responses":{"200":{"description":"A page of attendance regularizations.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttendanceRegularization"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an attendance regularization","description":"Asks to correct one day's attendance. Refused for an employee whose shift does not require punches — there is no missing-punch state to fix.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting attendance regularization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRegularization"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A regularisation for this employee and date is already awaiting a decision.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_regularizations/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an attendance regularization","responses":{"200":{"description":"The attendance regularization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRegularization"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance regularization in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_regularizations/{id}/approve":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Approve an attendance regularization","description":"Approving REWRITES that day's attendance record and stamps it `source: regularization`, which then protects it from the automatic recompute. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided attendance regularization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRegularization"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance regularization in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_regularizations/{id}/reject":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Reject an attendance regularization","description":"Approving REWRITES that day's attendance record and stamps it `source: regularization`, which then protects it from the automatic recompute. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided attendance regularization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRegularization"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance regularization in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/overtime_requests":{"get":{"summary":"List overtime requests","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected"]},"description":"Only requests in this state."},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the record's own date."},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."}],"responses":{"200":{"description":"A page of overtime requests.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OvertimeRequest"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an overtime request","description":"Claims overtime for one day. A workspace with auto-approval enabled returns the request already `approved`.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting overtime request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OvertimeRequest"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"An overtime request for this employee and date is already awaiting a decision.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/overtime_requests/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an overtime request","responses":{"200":{"description":"The overtime request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OvertimeRequest"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such overtime request in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/overtime_requests/{id}/approve":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Approve an overtime request","description":"Whether approval is what makes the minutes count toward pay depends on `overtime_require_approval` in the attendance settings. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided overtime request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OvertimeRequest"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such overtime request in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/overtime_requests/{id}/reject":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Reject an overtime request","description":"Whether approval is what makes the minutes count toward pay depends on `overtime_require_approval` in the attendance settings. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided overtime request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OvertimeRequest"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such overtime request in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/rest_day_swaps":{"get":{"summary":"List rest day swaps","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."}],"responses":{"200":{"description":"A page of rest day swaps.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RestDaySwap"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a rest day swap","description":"`worked_date` must be a rest day for that employee — a weekly off or a holiday — `off_date` must be an ordinary working day, and both must fall in the same calendar month.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting rest day swap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestDaySwap"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"One of the dates is already part of another swap. A rest day can be swapped once, and a substitute day can absorb one swap.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/rest_day_swaps/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a rest day swap","responses":{"200":{"description":"The rest day swap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestDaySwap"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such rest day swap in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a rest day swap","description":"Removes the swap, restoring both days to their ordinary classification.","responses":{"200":{"description":"The deleted rest day swap, so you have what was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestDaySwap"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such rest day swap in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employee_shifts":{"get":{"summary":"List employee shifts","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"shift_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only assignments of this shift."},{"name":"current","in":"query","schema":{"type":"boolean"},"description":"Only the assignment in force today."}],"responses":{"200":{"description":"A page of employee shifts.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeShift"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an employee shift","description":"Assigns a shift from a date, closing any open assignment the day before this one starts.\n\n**Worth doing straight after creating an employee.** Employee creation does not assign a shift, and an employee without one has no expected hours — so attendance has nothing to grade against and payroll cannot classify their days.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting employee shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeShift"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The request conflicts with the current state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employee_shifts/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an employee shift","responses":{"200":{"description":"The employee shift.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeShift"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee shift in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete an employee shift","description":"Removes the assignment and recomputes attendance over the period it covered, so any grading that depended on it resolves again.","responses":{"200":{"description":"The deleted employee shift, so you have what was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeShift"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee shift in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_sites":{"get":{"summary":"List attendance sites","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive"]},"description":"Only sites in this state."}],"responses":{"200":{"description":"A page of attendance sites.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttendanceSite"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create an attendance site","description":"Creates a geofenced site. `radius_meters` defaults to 150 and is bounded to 10–10000, matching what the app itself accepts.\n\nA site with no assigned employees accepts no punches — see the assignments sub-resource.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting attendance site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceSite"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The request conflicts with the current state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_sites/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an attendance site","responses":{"200":{"description":"The attendance site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceSite"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance site in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update an attendance site","description":"Only the fields present in the body are changed. `branch_id: null` detaches the site from its branch.","responses":{"200":{"description":"The updated attendance site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceSite"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance site in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete an attendance site","description":"Permanent. Assignments go with it; punch-attempt history survives with the site reference cleared.","responses":{"200":{"description":"The deleted attendance site, so you have what was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceSite"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance site in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_sites/{id}/assignments":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"List the employees assigned to a site","responses":{"200":{"description":"The assigned employee ids.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance site in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"put":{"summary":"Replace the employees assigned to a site","description":"Send the COMPLETE list, not a delta — it replaces whatever was assigned. An empty array unassigns everyone, which leaves the site accepting no punches.","responses":{"200":{"description":"The assigned employee ids after the change.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"400":{"description":"One of the employees is not in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such attendance site in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attendance_settings":{"get":{"summary":"Retrieve the attendance settings","description":"A workspace singleton, so there is no id. Read-only: these rules change how existing pay is calculated, which is not something an integration should be able to do in a single call.\n\nRead it before interpreting any attendance record — a `late_minutes` of 20 means nothing until you know the grace period was 15.","responses":{"200":{"description":"The settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceSettings"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_types":{"get":{"summary":"List leave types","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of leave types.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaveType"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Create a leave type","description":"Creates a leave type. `code` must be unique in the workspace.\n\nA type on its own grants nothing — the entitlement lives on a policy, which is configured in the app.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting leave type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveType"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A leave type with that code already exists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_types/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a leave type","responses":{"200":{"description":"The leave type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update a leave type","description":"Only the fields present in the body are changed.\n\n**Retiring a type is `is_active: false`, and there is no DELETE.** Allocations and applications reference a leave type for ever, so one is never removed — a DELETE here would answer 200 and leave the record in place, which is worse than not offering it.","responses":{"200":{"description":"The updated leave type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_policies":{"get":{"summary":"List leave policies","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"leave_type_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this leave type."}],"responses":{"200":{"description":"A page of leave policies.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeavePolicy"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_policies/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a leave policy","responses":{"200":{"description":"The leave policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeavePolicy"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave policy in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_groups":{"get":{"summary":"List leave groups","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of leave groups.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaveGroup"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_groups/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a leave group","responses":{"200":{"description":"The leave group.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveGroup"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave group in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_balances":{"get":{"summary":"List leave balances","parameters":[{"name":"employee_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"},"description":"Required. Balances are computed per employee."},{"name":"fiscal_year_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Defaults to the workspace's current fiscal year."}],"responses":{"200":{"description":"A page of leave balances.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaveBalance"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_applications":{"get":{"summary":"List leave applications","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records belonging to this employee."},{"name":"leave_type_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this leave type."},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected","cancelled"]},"description":"Only requests in this state."},{"name":"from_date","in":"query","schema":{"type":"string","format":"date"},"description":"Requests OVERLAPPING this day or later. A request running 1–5 March matches a window starting on the 3rd."},{"name":"to_date","in":"query","schema":{"type":"string","format":"date"},"description":"Requests overlapping this day or earlier."}],"responses":{"200":{"description":"A page of leave applications.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaveApplication"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"summary":"Apply for leave","description":"Applies on an employee's behalf.\n\n`total_days` is computed by the workspace, not taken from the span: rest days, holidays and the sandwich rule all bear on it, so a five-day range may consume three days or seven.\n\nRefused when the employee is ineligible under the policy (gender, tenure or employment type), when the balance is insufficient and the policy forbids a deficit, or when the dates overlap an existing request.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"The resulting leave application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveApplication"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"An overlapping leave request already exists for these dates.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_applications/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a leave application","responses":{"200":{"description":"The leave application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveApplication"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave application in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_applications/{id}/approve":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Approve a leave application","description":"Consumes the balance and marks every day of the request as `on_leave` on the employee’s attendance. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided leave application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveApplication"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave application in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_applications/{id}/reject":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Reject a leave application","description":"Requires a `reason` in the body — it is the only thing the employee sees, and a rejection they cannot act on is not a decision. Answers 409 if the request was already decided.","responses":{"200":{"description":"The decided leave application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveApplication"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave application in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/leave_applications/{id}/cancel":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"post":{"summary":"Cancel a leave application","description":"Withdraws a request. An approved one can only be cancelled before it starts; cancelling it releases the balance and clears the attendance marks. Requires a `reason`.","responses":{"200":{"description":"The decided leave application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveApplication"}}}},"400":{"description":"The request body failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such leave application in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"This request has already been decided.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_components":{"get":{"summary":"List salary components","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."},{"name":"type","in":"query","schema":{"type":"string"},"description":"earning, deduction, or employer_contribution."},{"name":"code","in":"query","schema":{"type":"string"},"description":"Look up one component by its code."}],"responses":{"200":{"description":"A page of salary components.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalaryComponent"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_components/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a salary component","responses":{"200":{"description":"The salary component.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryComponent"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such salary component in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_structures":{"get":{"summary":"List salary structures","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of salary structures.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalaryStructure"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_structures/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a salary structure","responses":{"200":{"description":"The salary structure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryStructure"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such salary structure in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_structure_components":{"get":{"summary":"List salary structure components","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"salary_structure_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only components of this structure."},{"name":"salary_component_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only rows for this component."}],"responses":{"200":{"description":"A page of salary structure components.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalaryStructureComponent"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_structure_components/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a salary structure component","responses":{"200":{"description":"The salary structure component.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryStructureComponent"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such salary structure component in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_assignments":{"get":{"summary":"List salary assignments","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"salary_structure_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only assignments on this structure."}],"responses":{"200":{"description":"A page of salary assignments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalaryAssignment"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_assignments/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a salary assignment","responses":{"200":{"description":"The salary assignment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryAssignment"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such salary assignment in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_runs":{"get":{"summary":"List payroll runs","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only runs in this state."},{"name":"source","in":"query","schema":{"type":"string"},"description":"processed or imported."},{"name":"month","in":"query","schema":{"type":"integer"},"description":"Calendar month, 1–12."},{"name":"year","in":"query","schema":{"type":"integer"},"description":"Calendar year."}],"responses":{"200":{"description":"A page of payroll runs.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PayrollRun"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_runs/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a payroll run","responses":{"200":{"description":"The payroll run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayrollRun"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such payroll run in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_entries":{"get":{"summary":"List payroll entries","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"payroll_run_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only entries in this run."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only entries in this state."}],"responses":{"200":{"description":"A page of payroll entries.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PayrollEntry"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_entries/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a payroll entry","responses":{"200":{"description":"The payroll entry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayrollEntry"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such payroll entry in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_entry_components":{"get":{"summary":"List payroll entry components","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"payroll_entry_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only lines on this entry."},{"name":"salary_component_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only lines for this component."},{"name":"type","in":"query","schema":{"type":"string"},"description":"earning, deduction, or employer_contribution."}],"responses":{"200":{"description":"A page of payroll entry components.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PayrollEntryComponent"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/payroll_entry_components/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a payroll entry component","responses":{"200":{"description":"The payroll entry component.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayrollEntryComponent"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such payroll entry component in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_slips":{"get":{"summary":"List salary slips","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"payroll_entry_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only slips for this entry."}],"responses":{"200":{"description":"A page of salary slips.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalarySlip"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/salary_slips/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a salary slip","responses":{"200":{"description":"The salary slip.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalarySlip"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such salary slip in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loan_types":{"get":{"summary":"List loan types","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of loan types.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoanType"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loan_types/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a loan type","responses":{"200":{"description":"The loan type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such loan type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loans":{"get":{"summary":"List loans","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"loan_type_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only loans of this kind."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only loans in this state."}],"responses":{"200":{"description":"A page of loans.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Loan"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loans/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a loan","responses":{"200":{"description":"The loan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Loan"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such loan in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loan_installments":{"get":{"summary":"List loan installments","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"loan_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only installments of this loan."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only installments in this state."},{"name":"due_month","in":"query","schema":{"type":"integer"},"description":"Calendar month due, 1–12."},{"name":"due_year","in":"query","schema":{"type":"integer"},"description":"Calendar year due."}],"responses":{"200":{"description":"A page of loan installments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoanInstallment"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/loan_installments/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a loan installment","responses":{"200":{"description":"The loan installment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanInstallment"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such loan installment in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_categories":{"get":{"summary":"List expense categories","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of expense categories.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseCategory"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_categories/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an expense category","responses":{"200":{"description":"The expense category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseCategory"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such expense category in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_claims":{"get":{"summary":"List expense claims","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only claims in this state."}],"responses":{"200":{"description":"A page of expense claims.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseClaim"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_claims/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an expense claim","responses":{"200":{"description":"The expense claim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseClaim"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such expense claim in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_claim_items":{"get":{"summary":"List expense claim items","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"claim_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only items on this claim."},{"name":"category_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only items in this category."},{"name":"expense_date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the expense date."},{"name":"expense_date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."}],"responses":{"200":{"description":"A page of expense claim items.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseClaimItem"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/expense_claim_items/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an expense claim item","responses":{"200":{"description":"The expense claim item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseClaimItem"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such expense claim item in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/document_types":{"get":{"summary":"List document types","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"code","in":"query","schema":{"type":"string"},"description":"Look up one type by its code."}],"responses":{"200":{"description":"A page of document types.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentType"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/document_types/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a document type","responses":{"200":{"description":"The document type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentType"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such document type in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employee_documents":{"get":{"summary":"List employee documents","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"document_type_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only documents of this type."},{"name":"verification_status","in":"query","schema":{"type":"string"},"description":"pending, verified, or rejected."}],"responses":{"200":{"description":"A page of employee documents.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeDocument"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employee_documents/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an employee document","responses":{"200":{"description":"The employee document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeDocument"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee document in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contracts":{"get":{"summary":"List contracts","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only contracts in this state."},{"name":"type","in":"query","schema":{"type":"string"},"description":"Only contracts of this kind."},{"name":"start_date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the contract start date."},{"name":"start_date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."},{"name":"end_date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the contract end date."},{"name":"end_date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."}],"responses":{"200":{"description":"A page of contracts.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contract"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contracts/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a contract","responses":{"200":{"description":"The contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contract"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such contract in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/hr_letters":{"get":{"summary":"List hr letters","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"letter_type","in":"query","schema":{"type":"string"},"description":"Only letters of this kind."},{"name":"reference_number","in":"query","schema":{"type":"string"},"description":"Look up one letter by its reference."},{"name":"issued_date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive lower bound on the issue date."},{"name":"issued_date_to","in":"query","schema":{"type":"string","format":"date"},"description":"Inclusive upper bound — the named day is included."}],"responses":{"200":{"description":"A page of hr letters.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HrLetter"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/hr_letters/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a hr letter","responses":{"200":{"description":"The hr letter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HrLetter"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such hr letter in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/hr_letter_requests":{"get":{"summary":"List hr letter requests","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"letter_type","in":"query","schema":{"type":"string"},"description":"Only requests for this kind of letter."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only requests in this state."}],"responses":{"200":{"description":"A page of hr letter requests.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HrLetterRequest"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/hr_letter_requests/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a hr letter request","responses":{"200":{"description":"The hr letter request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HrLetterRequest"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such hr letter request in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/asset_categories":{"get":{"summary":"List asset categories","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Filter by whether the record is in use."}],"responses":{"200":{"description":"A page of asset categories.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssetCategory"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/asset_categories/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an asset category","responses":{"200":{"description":"The asset category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetCategory"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such asset category in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/assets":{"get":{"summary":"List assets","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"category_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only assets in this category."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only assets in this state."},{"name":"condition","in":"query","schema":{"type":"string"},"description":"Only assets in this condition."},{"name":"asset_tag","in":"query","schema":{"type":"string"},"description":"Look up one asset by the workspace's own tag."},{"name":"include_deleted","in":"query","schema":{"type":"boolean","default":false},"description":"Include retired assets, flagged `deleted: true`. Required for a client syncing on `updated_since` to observe a retirement at all."}],"responses":{"200":{"description":"A page of assets.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Asset"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/assets/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an asset","responses":{"200":{"description":"The asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such asset in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/asset_assignments":{"get":{"summary":"List asset assignments","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"employee_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only records for this employee."},{"name":"asset_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only assignments of this asset."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only assignments in this state."}],"responses":{"200":{"description":"A page of asset assignments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssetAssignment"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/asset_assignments/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an asset assignment","responses":{"200":{"description":"The asset assignment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetAssignment"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such asset assignment in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/job_openings":{"get":{"summary":"List job openings","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only openings in this state."},{"name":"department_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only openings in this department."},{"name":"branch_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only openings at this branch."}],"responses":{"200":{"description":"A page of job openings.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/JobOpening"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/job_openings/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a job opening","responses":{"200":{"description":"The job opening.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobOpening"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such job opening in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/candidates":{"get":{"summary":"List candidates","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"email","in":"query","schema":{"type":"string"},"description":"Look up a candidate by email."}],"responses":{"200":{"description":"A page of candidates.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Candidate"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/candidates/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve a candidate","responses":{"200":{"description":"The candidate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Candidate"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such candidate in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/applications":{"get":{"summary":"List applications","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"candidate_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only this candidate’s applications."},{"name":"job_opening_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only applications to this opening."},{"name":"stage","in":"query","schema":{"type":"string"},"description":"Only applications at this stage."},{"name":"source","in":"query","schema":{"type":"string"},"description":"Only applications from this source."}],"responses":{"200":{"description":"A page of applications.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Application"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/applications/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an application","responses":{"200":{"description":"The application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such application in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/announcement_categories":{"get":{"summary":"List announcement categories","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"}],"responses":{"200":{"description":"A page of announcement categories.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AnnouncementCategory"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/announcement_categories/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an announcement category","responses":{"200":{"description":"The announcement category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementCategory"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such announcement category in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/announcements":{"get":{"summary":"List announcements","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/StartingAfter"},{"$ref":"#/components/parameters/UpdatedSince"},{"name":"category_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only announcements in this category."},{"name":"status","in":"query","schema":{"type":"string"},"description":"Only announcements in this state."},{"name":"priority","in":"query","schema":{"type":"string"},"description":"Only announcements at this priority."}],"responses":{"200":{"description":"A page of announcements.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Announcement"}},"has_more":{"type":"boolean","description":"True when another page is available."},"next_cursor":{"type":"string","nullable":true,"description":"Pass as `starting_after` to fetch the next page."}}}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/announcements/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an announcement","responses":{"200":{"description":"The announcement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Announcement"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such announcement in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/employees/{id}":{"parameters":[{"$ref":"#/components/parameters/ResourceId"}],"get":{"summary":"Retrieve an employee","responses":{"200":{"description":"The employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Update an employee","description":"Only the fields present in the body are changed.","responses":{"200":{"description":"The updated employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete an employee","description":"A soft delete. Returns the record with `deleted: true` rather than an empty body, so a syncing client sees the state it should mirror.","responses":{"200":{"description":"The deleted employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"401":{"description":"The API key is missing, malformed, revoked or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key does not carry the required scopes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such employee in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. See the RateLimit-* headers.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}}}