Skip to content

Jobs & Candidates

The hiring system manages open roles (jobs), applicants (candidates), job-candidate assignments, placements, and referrals. Used by Paula via the admin portal's Hiring section.

Jobs

GET /api/jobs

List jobs (admin use — all fields).

Auth: Required
Query params:

ParamTypeDescription
statusstringopen, closed, on_hold
productstringFilter by product
limitnumberDefault: 50

GET /api/jobs/public

List open jobs for public display (limited fields: id, title, product, location, job_type, description, requirements, created_at).

Auth: Public
Response: Filtered to status = 'open' only.


GET /api/jobs/public/:id

Get a single open job by ID (public, limited fields).

Auth: Public


GET /api/jobs/:id

Get a full job with all candidates.

Auth: Required
Response: All job fields + candidates array.


POST /api/jobs

Create a job.

Auth: Required

FieldTypeRequiredDescription
titlestringyesJob title
productstringnoDefault: studios
teamstringnoTeam name
descriptionstringnoFull job description
requirementsstringnoRequirements
locationstringnoDefault: Remote
job_typestringnocontract, full_time, part_time. Default: contract
statusstringnoDefault: open
salary_rangestringnoe.g. $80k-$120k

PATCH /api/jobs/:id

Update: title, product, team, description, requirements, location, job_type, status, salary_range.


GET /api/jobs/:id/activities

Get all activities for a job.

Auth: Required


GET /api/jobs/:id/notes

Get notes for a job.

Auth: Required


POST /api/jobs/:id/notes

Add a note to a job.

Auth: Required
Body: { "body": "Note text", "author": "user@email.com" }


DELETE /api/jobs/:id/notes/:noteId

Delete a job note.

Auth: Required


GET /api/jobs/:id/files

List files attached to a job.

Auth: Required


POST /api/jobs/:id/files

Upload a file to a job (stored in R2).

Auth: Required
Body: Multipart form with file field.


DELETE /api/jobs/:id/files/:fileId

Delete a job file.

Auth: Required


POST /api/jobs/:id/recommend-candidates

Use Claude AI to rank existing candidates by fit for this job.

Auth: Required
Response:

json
{
  "ok": true,
  "data": {
    "recommendations": [
      {
        "candidate_id": "cand_a1b2",
        "name": "Jane Smith",
        "score": 92,
        "reasoning": "Strong React + 5 years experience..."
      }
    ]
  }
}

Candidates

GET /api/candidates

List candidates with rich filtering and pagination.

Auth: Required
Query params:

ParamTypeDescription
job_idstringFilter by job
stagestringFilter by stage (applied, screening, interview, offer, hired, rejected)
productstringFilter by product
sourcestringFilter by source (linkedin, referral, direct, manatal)
locationstringLocation substring match
has_email1Only candidates with email
date_fromstringISO date — created after
date_tostringISO date — created before
show_archived1Include archived candidates
searchstringSearch name, email, company, title
limitnumberMax 200. Default: 50
offsetnumberPagination offset

Response:

json
{
  "ok": true,
  "data": [...],
  "total": 4228
}

GET /api/candidates/:id

Get a candidate with activity log.

Auth: Required
Response: All fields + activities[] + parsed resume_parsed object.


POST /api/candidates

Create a candidate.

Auth: Required

FieldTypeRequiredDescription
namestringyesFull name
emailstringnoEmail
phonestringnoPhone
linkedin_urlstringnoLinkedIn
locationstringnoLocation
current_titlestringnoCurrent job title
current_companystringnoCurrent employer
resume_textstringnoResume full text
resume_parsedobjectnoParsed resume JSON
sourcestringnolinkedin, referral, direct. Default: direct
stagestringnoDefault: applied
job_idstringnoAssociated job
notesstringnoRecruiter notes
assigned_tostringnoRecruiter email

PATCH /api/candidates/:id

Update: name, email, phone, linkedin_url, location, current_title, current_company, stage, notes, assigned_to, skills, availability, desired_roles, languages, github_url, salary_expectation, notice_period, tags, rating, archived_at.


POST /api/candidates/:id/activity

Log an activity for a candidate.

Auth: Required
Body: { "activity_type": "stage_change", "title": "...", "body": "..." }


GET /api/candidates/:id/files

List candidate files (resumes, attachments) from R2.


POST /api/candidates/:id/files

Upload a file for a candidate (R2 storage).


DELETE /api/candidates/:id/files/:fileId

Delete a candidate file.


GET /api/candidates/:id/notes

List candidate notes.


POST /api/candidates/:id/notes

Add a note.

Body: { "body": "...", "author": "..." }


PATCH /api/candidates/:id/notes/:noteId

Edit a note.


DELETE /api/candidates/:id/notes/:noteId

Delete a note.


POST /api/candidates/enrich-batch

Batch enrich candidates via Apollo API. Resolves missing emails, LinkedIn URLs, and company data for up to 50 candidates at a time.

Auth: Required
Body: { "candidate_ids": ["cand_1", "cand_2", ...] }


POST /api/enrich/:contact_id

Enrich a CRM contact with Apollo data (email, phone, LinkedIn, company).

Auth: Required


POST /api/enrich-company/:company_id

Enrich a CRM company with Apollo data (industry, employee count, LinkedIn).

Auth: Required


Candidate Segments

Segments are saved filters for targeting groups of candidates in campaigns.

POST /api/candidate-segments/preview

Preview candidates that would match a segment definition.

Auth: Required
Body: { "filters": { "skills": [...], "location": "...", "stage": "..." } }


GET /api/candidate-segments

List all saved segments.


POST /api/candidate-segments

Create a segment.

Body: { "name": "...", "description": "...", "filters": {...} }


GET /api/candidate-segments/:id

Get a segment.


PATCH /api/candidate-segments/:id

Update a segment.


DELETE /api/candidate-segments/:id

Delete a segment.

Sprint Mode LLC — Internal Platform Documentation