> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Applicant Tracking System (ATS)

> Recruit, evaluate, and hire candidates end to end — post jobs, collect public applications, run interviews, extend and accept offers, and measure recruiting performance.

## Overview

The Applicant Tracking System (HR-09) covers the full hiring lifecycle — from a published job posting through a candidate's public application, interviews and scorecards, an offer, and the hire that creates the employee record. Open it from **HR → Recruiting (ATS)**.

<Frame caption="The recruiting hub is the entry point for postings, applications, interviews, offers, and analytics.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/recruiting-hub.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=55840e4179773ee99af391a9c9bced9d" alt="ATS recruiting hub" width="1440" height="2272" data-path="images/ats/recruiting-hub.png" />
</Frame>

## Job postings

Create a posting linked to an open position, then **Publish** it. Only published postings are reachable from the public careers page.

<Frame caption="Job postings list. Draft postings can be edited; publishing makes a posting public.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/job-postings.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=35a14e0f2744b681be35346a77472102" alt="ATS job postings" width="1440" height="900" data-path="images/ats/job-postings.png" />
</Frame>

<Note>
  Publishing a posting transitions it from `draft` to `published` and stamps `published_at` — the start of the time-to-fill clock used by analytics.
</Note>

## The public careers page

Each published posting has a public, unauthenticated careers URL at `/careers/:postingId`. Candidates view the role and apply without an account; the application is created server-side and the candidate sees an on-screen confirmation.

<Frame caption="The public careers + apply page for a published posting. No sign-in required.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/careers-apply.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=0941be3d832cda94dce43197c2e50e34" alt="Public careers and apply page" width="1440" height="900" data-path="images/ats/careers-apply.png" />
</Frame>

<Note>
  Public applications are accepted through a service-role edge function with per-IP rate limiting; a candidate record is found-or-created by email and a duplicate application to the same posting is collapsed into the existing one.
</Note>

## The application pipeline

Applications progress through stages — `applied → screening → interview → offer → hired` (or `rejected`/`withdrawn`). Recruiters screen, advance, and manage candidates from the pipeline.

<Frame caption="The application pipeline, grouped by stage.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/applications-pipeline.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=92f8b270a5d6edffe8d1a312081f5ad1" alt="ATS application pipeline" width="1440" height="900" data-path="images/ats/applications-pipeline.png" />
</Frame>

## Interviews & scorecards

Schedule interviews from an application and capture **structured feedback** — per-competency ratings (overall, technical, communication, cultural fit, problem solving) plus an overall recommendation (`strong_yes … strong_no`). Feedback is attributed to the interviewing employee and aggregated for the hiring manager.

## Offers — sending and accepting

Offers move through `draft → pending approval → approved → sent → accepted`. From a **sent** offer, the **Accept Offer** action records the candidate's acceptance and performs the hire.

<Frame caption="A sent offer. The Accept Offer action records acceptance and creates the linked employee.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/offer-detail-accept.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=2988a8f8901d05f80d1cc50e402a8d4d" alt="Offer detail with the Accept Offer action" width="1440" height="900" data-path="images/ats/offer-detail-accept.png" />
</Frame>

<Note>
  Accepting an offer is idempotent: it creates **exactly one** employee record (with its platform identity) and **one** hire transition, marks the application `hired`, and emits the `hr_employee_hired` event that drives HR-03 onboarding, IT-08 provisioning, and PF-10 notifications. Re-accepting the same offer is a safe no-op.
</Note>

### Candidate self-service from the portal

Candidates can review, accept, or decline their own offers from the candidate portal — the self-service counterpart to the recruiter **Accept Offer** action. After a recruiter sends an offer, the candidate sees a **My Offers** link on their portal dashboard at `/hr/candidate-portal/offers`, opens an individual offer at `/hr/candidate-portal/offers/:offerId`, and confirms an **Accept** or **Decline** in a dialog.

The portal only surfaces offers in `sent`, `accepted`, `rejected`, `expired`, or `withdrawn` status — internal drafts and pending-approval offers are never exposed. Accepting from the portal runs the same idempotent hire pipeline as the admin action and emits `hr_employee_hired`. Declining transitions the offer to `rejected`, stamps `responded_at`, and mirrors the decline onto the linked application.

<Note>
  The portal uses a candidate-scoped JWT (not Supabase Auth), and every request is enforced against the offer's owning `candidate_id` + `organization_id`. A candidate cannot view or act on another candidate's offer.
</Note>

| Action                      | Method + path                                                           | Auth       |
| --------------------------- | ----------------------------------------------------------------------- | ---------- |
| List the candidate's offers | `GET /functions/v1/hr-portal-offers`                                    | Portal JWT |
| Accept an offer             | `POST /functions/v1/hr-offer-accept` with `{ type: "portal", offerId }` | Portal JWT |
| Decline an offer            | `POST /functions/v1/hr-portal-offer-decline` with `{ offerId, notes? }` | Portal JWT |

## Analytics

### Time to fill

Measures the days from a posting's `published_at` to a hire's `hired_at`, with breakdowns and a target benchmark.

<Frame caption="Time-to-fill analytics, computed from real hiring data.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/analytics-time-to-fill.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=cfa62e8b5548a246a67408d6047fcf62" alt="Time to fill analytics" width="1440" height="1539" data-path="images/ats/analytics-time-to-fill.png" />
</Frame>

### EEO reporting

Aggregates applicant-pool and hired-candidate demographics with adverse-impact analysis and data-completeness. EEO data is stored in a restricted table readable only by compliance/admin roles.

<Frame caption="EEO reporting dashboard with applicant-pool demographics and adverse-impact analysis.">
  <img src="https://mintcdn.com/encoreos/9uGfYOeeHogjmoRk/images/ats/analytics-eeo-reporting.png?fit=max&auto=format&n=9uGfYOeeHogjmoRk&q=85&s=cfb9f09b857cac92a9551e3c908e5564" alt="EEO reporting analytics" width="1440" height="915" data-path="images/ats/analytics-eeo-reporting.png" />
</Frame>

## Permissions

| Capability                                                        | Required access                                                          |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------ |
| Create/publish postings, manage applications, schedule interviews | `org_admin` / `hr_admin` / `hr_manager`, or `hr.employees.*` permissions |
| Accept an offer (creates an employee account)                     | `org_admin` / `hr_admin` / `hr_manager`, or `hr.employees.create`        |
| View EEO reporting                                                | Compliance / org-admin roles only                                        |
| Apply via the public careers page                                 | No account (anonymous)                                                   |

## Related

* Source spec: `specs/hr/specs/HR-09-applicant-tracking-system.md`
* [Proliant payroll integration](/hr/proliant-setup)
