The recruitment module takes a role from a budget-approved job posting to a signed offer: a public careers page, a candidate pipeline, interviews with scorecards, offers that a second person approves, and a private page where the new hire signs and chooses their equipment. For the step-by-step, see the guide Hire someone.
An administrator uses it to open roles, decide who may see and move candidates, and keep the approval steps separate from the people who ask for them.
Two People For Every Money Decision
A job’s budget is approved by someone with the finance permission who did not create the job, and an offer is approved by someone other than the person who set its terms. A signed offer is reversed only by a rescission that a second person approves. An administrator is exempt from all three rules (the budget approval, the offer approval and the rescission approval), so a company with one administrator is never locked out of hiring. An administrator approving the budget of a job they created is recorded in the audit log as an exemption.
Plan
Recruitment is included from Team. On a plan without it none of the menu items below are shown. All Zonitix pricing is per instance, never per seat.
Where Everything Is In The Menu
A person sees a menu item only when their role allows it. Which permission shows which item is listed under Technical detail at the end of this page.
Menu Item
What It Is
HR & TalentRecruitment Overview
The hiring home page, with an Overview tab and a Reports tab.
HR & TalentJob Postings
Requisitions, their budget approval, the careers page and the job-board feeds.
HR & TalentCandidate Pipeline
Every candidate the viewer may see, by stage.
HR & TalentTemplates
Offer letters and interview guides. The Hiring policies page is opened from a link on this page.
HR & TalentOffer Approvals
Offers waiting for a second person to approve.
My WorkMy Interviews
The interviews assigned to the signed-in person, and their scorecards.
My WorkInternal Referrals
Refer someone for an open role and follow their progress.
The command palette (Ctrl+K or Cmd+K) also lists Hiring Templates, Hiring Policies and Hiring Reports. Those are the HR & TalentTemplates page, the Hiring policies page reached from it, and the Reports tab of HR & TalentRecruitment Overview.
Who Sees Which Candidate
An administrator or a person who manages recruitment can act on every candidate. Everyone else sees a candidate only when one of these is true: they are the candidate’s owner, they own or are the hiring manager of the candidate’s job, or they are assigned an interview with the candidate. The same rule limits the pipeline list, a candidate’s messages and the actions on a candidate; a candidate outside it is treated as if it did not exist.
The Pages Of This Reference
The detail of recruitment is on its own pages, one per subject. Each opens with a short description in plain words, followed by the technical part. The permissions and the typed fields of the API objects are in the technical part of this page.
Requisitions & Careers Page: requisitions and their budget approval, the careers page, job alerts and job-board feeds.
Candidate Pipeline & Messages: the stages, the rules on moving a candidate, actions on several candidates and messages.
Interviews & Scorecards: assigning interviews, the candidate’s scheduling page, scorecards and reminders.
The plain explanation is above. This part is for IT and developers: the exact settings, permission names, API addresses and data fields behind it. Closed: select the heading above to open it. While it is closed, your browser’s find-on-page (Ctrl+F or Cmd+F) does not search this part.
Permissions
Give these to people through a role in Access Control. A permission other than manage_recruitment does not by itself show every candidate; see Who Sees Which Candidate.
Permission
What It Allows
manage_recruitment
Everything in recruitment: requisitions, every candidate, templates, policies, sending and withdrawing offers, reassigning owners. It cannot approve a budget.
view_recruitment
Read requisitions, the candidates the holder is connected to, message threads, templates and hiring reports. No notes, and no moving, rejecting or messaging candidates.
source_candidates
Add and screen candidates, move, tag, reject and message the candidates the holder is connected to, and write notes.
schedule_interviews
Assign, reschedule and cancel interviews, and send time options.
conduct_interview
See My Interviews, submit scorecards, and work on the candidates the holder interviews.
approve_offer
See Offer Approvals, set offer terms, approve or withhold an offer, send it, and request or approve a rescission.
manage_finance
Approve or refuse a requisition budget, and approve offers.
review_executive_packet
Read candidates, interviews and hiring reports for a final review.
view_referrals
See Internal Referrals and submit referrals.
Which Permission Shows Which Menu Item
Every row also needs recruitment on the plan (the recruitment licence entitlement). A request for a candidate outside the caller’s visibility rule is answered with 404, as if the candidate did not exist.
The full route list, with the permission on every route, is in the API reference under Recruitment & Hiring.
Data Objects (Typed Fields)
In plain words: a call to the API answers with objects such as a requisition, a candidate, an offer or an interview. This section lists what is inside each one: every field, its type, and whether it can be empty. Open an object to see its fields. The routes that return them are in the API reference under the six groups whose names start with Recruitment, where a capitalised name in a row’s returns line is one of these objects.
Types.integer, number, string, boolean, object and arrays written as string[]. string (date-time) is ISO 8601; string (date) is YYYY-MM-DD. A type followed by a colon and values separated by | takes only those values. A capitalised type is another object in this list.
The third column. “nullable” means the field can be null; “optional” means the key can be missing; “no” means neither. “read-only” means the server sets the field and a write does not change it. Do not fail on a field you do not recognise: a reply can carry fields beyond these. A card marked “request body” is what you send, not what comes back: its third column is headed Required, where “required” means the field must be sent and every other field is optional.
Who sees what. Offer pay (salary, signOnBonus) is null for a caller who may not see offer compensation. Another interviewer’s score and feedback are masked until you have submitted your own scorecard, unless you manage recruitment or are the hiring manager of the requisition.
Never returned: the link a candidate signs an offer with, and the link to the candidate’s offer portal.
JobPostingin a reply36 fields
A requisition.
Field
Type
Null / optional / read-only
Note
id
integer
read-only
title
string
no
description
string
nullable
department
string
nullable
status
string: Draft | Open | Published | Closed | Filled | On Hold
no
Only Published roles are on the careers site.
financeApprovalStatus
string: Pending | Approved | Rejected
read-only
The headcount budget gate.
location
string
nullable
employmentType
string
nullable
seniority
string
nullable
workMode
string
nullable
minExperienceMonths
integer
nullable
currency
string
nullable
salaryRange
string
nullable
salaryMin
integer
nullable
salaryMax
integer
nullable
payPeriod
string
nullable
competencies
array
no
requirements
array
no
applicationQuestions
object[]
no
Each has id, label, type, required and options on the careers site.
hiringManagerId
integer
nullable
ownerId
integer
nullable
personaId
integer
nullable
createdById
integer
nullable, read-only
financeApprovedById
integer
nullable, read-only
financeApprovedAt
string (date-time)
nullable, read-only
financeRejectionReason
string
nullable, read-only
financeRequestedAt
string (date-time)
nullable, read-only
isTalentPool
boolean
read-only
true only for the talent-pool requisition, which the list leaves out.
createdAt
string (date-time)
read-only
updatedAt
string (date-time)
read-only
candidateCount
integer
read-only
In the list only: every applicant, not the preview.
stageCounts
object
nullable, read-only
In the list only: { "<STAGE IN CAPITALS>": integer }; null when the role has no candidates.
Candidates
object[]
read-only
In the list only: the newest applicants in your own candidate scope, each { id, firstName, lastName, email, stage, matchScore, jobPostingId }.
One email to or from a candidate, as the message list returns it.
Field
Type
Null / optional / read-only
Note
id
integer
read-only
direction
string: outbound | inbound
no
fromAddr
string
nullable
toAddr
string
nullable
subject
string
nullable
body
string
nullable
createdAt
string (date-time)
read-only
sentById
integer
nullable
The user who sent an outbound message.
Referralin a reply8 fields
Field
Type
Null / optional / read-only
Note
id
integer
read-only
userId
integer
no
The employee who made the referral.
candidateId
integer
no
notes
string
nullable
status
string: Pending | Reviewed | Hired | Rejected
no
createdAt
string (date-time)
read-only
updatedAt
string (date-time)
read-only
Candidate
object
read-only
In the list only: { id, firstName, lastName, stage, source, createdAt, Job:{ id, title, department } }.
JobPostingWriterequest body20 fields
Create and update take the same keys; an update changes only the keys you send. The budget-approval fields and the creator are set by the server and are not read from the body.
Field
Type
Required
Note
title
string
required on create
description
string
optional
department
string
optional
status
string: Draft | Open | Published | Closed | Filled | On Hold
optional
Open and Published are refused with 409 until the headcount budget is approved.
location
string
optional
employmentType
string
optional
seniority
string
optional
workMode
string
optional
minExperienceMonths
integer
optional, null clears it
A number, or text that is a number: rounded, 0 to 2147483647. Blank is stored as empty; anything else answers 400 INVALID_NUMBER.
currency
string
optional
salaryRange
string
optional
salaryMin
integer
optional, null clears it
Read the same way as minExperienceMonths.
salaryMax
integer
optional, null clears it
Read the same way as minExperienceMonths.
payPeriod
string
optional
competencies
array
optional
requirements
array
optional
applicationQuestions
object[]
optional
The extra questions on the public application form.
hiringManagerId
integer
optional, null clears it
ownerId
integer
optional, null clears it
personaId
integer
optional, null clears it
Assigning a persona is checked against what you are allowed to grant.
CandidateCreaterequest body7 fields
A candidate added by a signed-in recruiter. The stage, the scores and the consent fields are set by the server.
Field
Type
Required
Note
jobPostingId
integer
required
email
string (email)
required
Stored in one normalised spelling. The same email on the same requisition answers 409.
firstName
string
required
lastName
string
required
phoneNumber
string
optional
Stored encrypted.
source
string
optional
ownerId
integer
optional
Read only from a caller who holds manage_recruitment. Otherwise the candidate takes the owner of the requisition, or you when it has none.
CandidateBulkActionrequest body8 fields
One action for many candidates. Each candidate is handled on its own and lands in succeeded, skipped or failed.
reject only: the rejection email is sent unless this is false.
reason
string
optional
reject only.
ownerId
integer
optional, null clears it
reassign only.
add
string[]
optional
tag only: labels to add.
remove
string[]
optional
tag only: labels to remove.
CandidateTagsUpdaterequest body2 fields
A label is trimmed and cut to 40 characters; labels that differ only in capitalisation count as one; a candidate keeps at most 30.
Field
Type
Required
Note
add
string[]
optional
remove
string[]
optional
Matched without regard to capitalisation.
CandidateNoteCreaterequest body2 fields
Field
Type
Required
Note
body
string
required
Trimmed and cut to 5000 characters; empty answers 400.
mentions
integer[]
optional
User ids to notify. Values that are not positive whole numbers, and repeats, are dropped.
CandidateMessageSendrequest body2 fields
Field
Type
Required
Note
subject
string
required
Trimmed and cut to 500 characters.
body
string
required
Trimmed. A blank line starts a new paragraph in the email.
InterviewCreaterequest body7 fields
Field
Type
Required
Note
interviewerId
integer
required
A person who is allowed to conduct interviews.
scheduledAt
string (date-time)
optional, null clears it
Text that is not a date answers 400 INVALID_TIME. Without it the interview is created with no time.
sequence
integer
optional
The round number. Default 1.
interviewTemplateId
integer
optional
isShadow
boolean
optional
Default false.
durationMins
integer
optional
Used when checking the interviewer's other bookings.
allowOverlap
boolean
optional
true books the time although the interviewer already has an interview then.
InterviewSlotsProposerequest body6 fields
Offers the candidate a choice of times. Times in the past, times that are not dates and repeats are dropped, and the first 10 are kept.
Field
Type
Required
Note
interviewerId
integer
required
400 INTERVIEWER_REQUIRED without it.
slots
string (date-time)[]
required
At least two usable times, or the answer is 400 NOT_ENOUGH_SLOTS.
interviewTemplateId
integer
optional
durationMins
integer
optional
allowOverlap
boolean
optional
Without it, times that clash with the interviewer's bookings are dropped, and fewer than two left answers 409 DOUBLE_BOOKED.
isShadow
boolean
optional
Default false.
ScorecardSubmitrequest body3 fields
Marks the interview Completed.
Field
Type
Required
Note
score
integer
optional
1 to 5; anything else answers 400 INVALID_SCORE.
feedback
string
optional
structuredFeedback
object
optional
Your marks and notes per competency. The recommendation is carried inside it.
InterviewQuestionInputrequest body8 fields
Field
Type
Required
Note
questionText
string
required
category
string
optional
context
string
optional
idealAnswer
string
optional
weight
integer
optional
Default 1.
mustHave
boolean
optional
Default false.
anchors
object
optional
order
integer
optional
Defaults to the position in the list.
InterviewTemplateWriterequest body5 fields
Create and update take the same keys. On an update, sending questions replaces the question list; leaving it out keeps the questions as they are.
Field
Type
Required
Note
name
string
required on create
description
string
optional
roundName
string
optional
jobPostingId
integer
optional, null clears it
null makes the template available to every requisition.
questions
InterviewQuestionInput[]
optional
OfferTemplateWriterequest body4 fields
Create and update take the same keys; an update changes only the keys you send.
Field
Type
Required
Note
name
string
required on create
body
string
required on create
The text of the offer letter.
jobPostingId
integer
optional, null clears it
null makes the template available to every requisition.
supportingDocs
object[]
optional
At most 20. A link is { type:"link", label, url } with an http or https address; an uploaded file is { type:"file", label, storedName, filename?, size? } as POST /recruitment/offer-documents returns it. An entry without a label, or with an address or file name that does not pass the check, is dropped.
OfferTermsWriterequest body8 fields
The terms of a candidate's offer. Only the keys you send are changed; an empty text or null clears a value. Changing the terms of an approved offer sends it back for approval.
Field
Type
Required
Note
salary
number
optional, null clears it
Not negative, or the answer is 400.
currency
string
optional, null clears it
payPeriod
string
optional, null clears it
startDate
string (date)
optional
YYYY-MM-DD, or the answer is 400.
level
string
optional, null clears it
targetBonusPct
integer
optional, null clears it
0 to 100; rounded to a whole number.
signOnBonus
number
optional, null clears it
Not negative.
hiringManagerId
integer
optional, null clears it
Written to the requisition, not the offer.
OfferBulkDecisionrequest body4 fields
Approve or refuse many offers. Each one goes through the same checks as the single routes and lands in succeeded or failed.
Field
Type
Required
Note
ids
integer[]
required
1 to 200 candidate ids.
approve
boolean
required
Only true approves; any other value refuses.
reason
string
optional
Stored with a refusal.
termsVersions
object
optional
{ "<candidate id>": string }: the version of the terms you saw for each offer, cut to 64 characters. An offer whose terms changed since lands in failed.
RequisitionOwnerWriterequest body2 fields
Field
Type
Required
Note
ownerId
integer
optional, null clears it
A user id. null, 0 or a missing key leaves the requisition without an owner.
cascade
boolean
optional
true also moves the requisition's candidates that belonged to the previous owner or had none. A candidate given to someone else by hand keeps that owner.
CandidateOwnerWriterequest body1 field
Field
Type
Required
Note
ownerId
integer
optional, null clears it
A user id. null, 0 or a missing key leaves the candidate without an owner.
BudgetRefusalrequest body1 field
Field
Type
Required
Note
reason
string
required
Trimmed; at least 3 characters, or the answer is 400 with code REASON_REQUIRED. Cut to 1000 characters and stored on the requisition.
CompetencySuggestrequest body2 fields
Field
Type
Required
Note
jobTitle
string
required
Blank is refused with 400.
jobDescription
string
optional
JobDescriptionSuggestrequest body1 field
The whole body is passed to the model as context, so the other fields of the requisition form may be sent with it.
Field
Type
Required
Note
jobTitle
string
required
Blank is refused with 400.
CandidateStageWriterequest body1 field
Field
Type
Required
Note
stage
string
required
Sourced, Screen, Interview, Offer, Hired or Rejected, in any capitalisation.
CandidateRejectrequest body2 fields
Field
Type
Required
Note
sendEmail
boolean
optional
Whether the candidate is sent the rejection email.
reason
string
optional
InterviewReschedulerequest body3 fields
Field
Type
Required
Note
scheduledAt
string (date-time)
required
Text that is not a date is refused with 400, code INVALID_TIME.
durationMins
integer
optional
allowOverlap
boolean
optional
Only the value true books the time although the interviewer already has an interview then.
InterviewCancelrequest body1 field
Field
Type
Required
Note
reason
string
optional
Cut to 500 characters.
DraftForRequisitionrequest body1 field
Asks for a generated draft: interview questions, or an offer template.
Field
Type
Required
Note
jobPostingId
integer
optional
The requisition used as context. Without it the draft is written for a general role.
OfferGatePolicyWriterequest body1 field
Field
Type
Required
Note
requireScorecardsBeforeOffer
boolean
required
Anything that is not true or false is refused with 400.
OfferApproverequest body1 field
Field
Type
Required
Note
termsVersion
string
optional
The version of the terms the approver saw; cut to 64 characters. When it no longer matches the stored terms the answer is 409, code OFFER_TERMS_CHANGED.
OfferRejectrequest body1 field
Field
Type
Required
Note
reason
string
optional
OfferDeclineReasonrequest body1 field
Field
Type
Required
Note
reason
string
optional
Trimmed and cut to 2000 characters. Blank, or anything that is not text, clears the stored reason.
OfferRescindRequestrequest body1 field
Field
Type
Required
Note
reason
string
required
Blank is refused with 400, code REASON_REQUIRED.
OfferSendrequest body1 field
Field
Type
Required
Note
offerTemplateId
integer | null
optional
The offer template the contract is generated from. null sends the offer with no template; a missing key keeps the template already on the offer.
AssistantQueryrequest body1 field
Field
Type
Required
Note
query
string
required
The question. The streaming route refuses a blank one with 400.
FeedbackRefinerequest body1 field
Field
Type
Required
Note
text
string
required
The feedback text to tidy.
JobAlertSubscriberequest body4 fields
Field
Type
Required
Note
email
string
required
Trimmed, lower-cased and cut to 200 characters; must look like an address.
consent
boolean
required
Must be true.
department
string
optional
Cut to 120 characters. Without it the alert covers every department.
locale
string
optional
Cut to 8 characters.
JobAlertTokenrequest body1 field
Field
Type
Required
Note
token
string
required
The token from the link in the email.
SelfScheduleChoicerequest body1 field
Field
Type
Required
Note
chosen
string (date-time)
required
One of the times offered by the GET on the same path; any other time is refused with 400, code SLOT_NOT_OFFERED.