Skip to content
HRTEQDocs
Documentation API

DocsRecruitment

Applicants

Intake, numbering, duplicate detection, source attribution and résumé parsing — everything that happens before an applicant is endorsed to a position.

An applicant is a person, created once and kept. This page covers intake and the applicant record itself; the moment they are endorsed to a position the workflow moves onto the application, which is covered in Pipeline.

Creating an applicant#

The minimum is a first name, a last name, one contact route, and consent. Everything else can be filled in later — including by the applicant themselves through the portal.

Required on create.
FieldRule
firstName1–80 characters.
lastName1–80 characters.
mobile or emailAt least one must be present. Omitting both returns 400 with a plain message rather than a field error.
dataPrivacyConsentMust be literally true. Not a boolean that happens to be truthy — the schema requires the literal value.

Optional fields cover the rest of a Philippine bio-data: middleName, suffix, sex, birthDate, civilStatus, the address levels addressLine / cityMun / province / region, passportNo, sourceChannel and notes. Government identifiers — SSS, PhilHealth, Pag-IBIG, TIN, NBI clearance number — live on the record and are filled in as documents arrive.

Terminal
curl -X POST "$API_URL/v1/applicants" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: $CSRF" \
  --cookie "hrteq_session=$SESSION" \
  -d '{
    "firstName": "Maria",
    "middleName": "Cruz",
    "lastName": "Santos",
    "sex": "FEMALE",
    "birthDate": "1994-03-18",
    "civilStatus": "SINGLE",
    "mobile": "+639171234567",
    "email": "maria.santos@example.com",
    "cityMun": "Quezon City",
    "province": "Metro Manila",
    "passportNo": "P1234567A",
    "sourceChannel": "WALK_IN",
    "dataPrivacyConsent": true
  }'

# 201
# { "ok": true, "data": { "id": "...", "applicantNo": "APP-2026-000001" } }

What the server does on create#

  1. Checks the caller can create applicants. A Receptionist can; a Liaison Officer cannot.
  2. Rejects the request if neither a mobile number nor an email address was given.
  3. Looks for a duplicate on passport number, mobile or email within your organization.
  4. Allocates the next applicantNo for the year inside a transaction.
  5. Sets status to LEAD, stamps dataPrivacyConsentAt to now, and sets retentionExpiresAt to three years out.
  6. Records who created the record, which is what makes the receptionist own-draft exception work.
  7. Writes two audit rows: applicant.created and privacy.consent_recorded.

Numbering#

Applicant numbers are per-organization and per-year, formatted APP-<year>-<six digits>APP-2026-000001. Allocation happens inside the create transaction, so two simultaneous walk-ins cannot collide. The number is searchable alongside names, email and mobile.

Duplicate detection#

Before creating, the server searches your organization for an existing applicant matching any of the identifiers supplied — passport number, mobile, or email. A match returns 409 naming the existing person and their applicant number, so the officer at the front desk can go and find the record instead of creating a second one.

The check is scoped to your organization. Two agencies can each hold a record for the same person. There is no cross-tenant applicant registry, by design.

Applicant status#

StatusMeaning
LEADCreated but not yet working through a job order. The status every applicant starts at.
ACTIVEIn progress against at least one position.
DEPLOYEDSet automatically when any of their applications reaches the DEPLOYED stage, so lists agree with the board.
INACTIVEDormant. Not deleted — the record and its documents remain.
BLACKLISTEDExcluded from endorsement. A deliberate, recorded decision.

This status is for filtering and reporting. It is not the workflow — that lives on the application. See Core concepts.

Source attribution#

Every applicant carries a sourceChannel, defaulting to WALK_IN, plus UTM fields and an optional referredBy. Together they answer which channel actually produces deployments rather than merely producing leads.

  • WALK_IN — the front desk. The default.
  • REFERRAL — an existing worker or contact; pair it with referredBy.
  • FACEBOOK, TIKTOK, GOOGLE — paid or organic social and search.
  • JOB_BOARD — your own published board or an external one.
  • JOB_FAIR — a provincial or municipal recruitment event.
  • ONLINE_FORM — your website form posting to the API.
  • OTHER — everything else.

Searching and paging#

The list endpoint takes q, status, page and pageSize. q matches case-insensitively across applicant number, first name, last name, email and mobile. pageSize defaults to 30 and is capped at 100. Results are ordered by most recently updated, which keeps the person you just touched at the top. In the UI the search box is debounced by 250 ms.

The profile record#

Beyond bio-data, an applicant carries four related collections and a set of documents.

Work experience
Employer, position, country and dates. Ordered most recent first. This is what a principal reads before shortlisting.
Education
Level, institution and completion.
Skills
Structured entries used for matching against a position’s required skills.
Training
TESDA and other certifications, mirrored by the corresponding document types.

Applicant-level documents — passport, PSA records, NBI clearance, résumé, DMW e-Registration — are uploaded here once and reused by every application the person is part of. See Documents.

Résumé parsing#

Uploading a résumé can queue a parse job on the background worker. The result lands in parsedProfile and the record moves through parseStatus, which exists so a machine extraction is always reviewed by a person before it overwrites anything.

parseStatusMeaning
NONENo parse has been attempted.
QUEUEDWaiting on the worker.
RUNNINGIn progress.
READY_FOR_REVIEWExtraction finished. Nothing has been written to the profile yet.
APPLIEDAn officer accepted the extraction; the audit row is applicant.parse_applied.
FAILEDThe document could not be read. The file is untouched.

Editing and the own-draft rule#

Updates go through a partial version of the create schema. Two things are worth knowing: dataPrivacyConsent is stripped from updates — consent is a recorded event, not a toggle — and a Receptionist may update an applicant only if they created it. Every update writes applicant.updated.

Privacy obligations attach at creation#

Consent and retention are set on the first write. Creating an applicant stamps consent and sets a three-year retention horizon. That horizon is swept nightly and raises a review task rather than deleting anything. Read Data privacy and retention before you import a spreadsheet of old leads.
Was this page helpful?