Jobs.
A job is a job post (vacancy): draft → published → paused → closed/filled. Creation runs the AI composer for free; everything long-running returns a run_id you can poll at GET /v1/runs/{id}.
Create a job#
/v1/jobs| Field | Type | Description | |
|---|---|---|---|
| title | string | required | Role title, 2–200 chars. The only required field. |
| seniority | enum | optional | junior · mid · senior · lead · director · executive |
| years_experience_min / _max | integer | optional | Experience band, 0–60. |
| location | string | optional | Free-text location shown on the posting. |
| location_type | enum | default: onsite | onsite · remote · hybrid |
| employment_type | enum | default: full_time | full_time · part_time · contract · internship |
| salary_min / _max | integer | optional | Salary band in salary_currency per salary_period. |
| salary_currency | string(3) | default: USD | ISO 4217 code (AED, SAR, EGP, …). |
| salary_period | enum | default: month | month · year · hour |
| salary_visible | boolean | default: false | Show the band on the public job page. |
| skills | string[] | optional | Up to 30 key skills — they seed the JD and the screening rubric. |
| language | string | default: en | Primary JD language. |
| bilingual | boolean | default: false | Also generate the Arabic (MSA) JD — written natively, not translated. |
| extra_notes | string | optional | Anything the composer should know (team, stack, visa, shift patterns…). Max 2000 chars. |
| auto_generate | boolean | default: true | Start the free jd_generate run immediately. When false, you get an empty draft and run_id is null — bring your own JD via PATCH. |
curl -X POST https://hire.whizztech.ai/v1/jobs \
-H "Authorization: Bearer $HIRE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: fleet-ops-001" \
-d '{
"title": "Fleet Operations Manager",
"seniority": "senior",
"years_experience_min": 5,
"location": "Dubai, UAE",
"location_type": "onsite",
"salary_min": 18000,
"salary_max": 25000,
"salary_currency": "AED",
"salary_visible": true,
"skills": ["fleet management", "route optimization", "SAP"],
"bilingual": true
}'{
"job": {
"id": "4d1a8f36-9e02-47b8-b7c4-3a92d5e60f18",
"object": "job",
"status": "draft",
"slug": "fleet-operations-manager-9f2c1a",
"title": "Fleet Operations Manager",
"seniority": "senior",
"location": "Dubai, UAE",
"location_type": "onsite",
"employment_type": "full_time",
"language": "en",
"description_md": "",
"description_ar_md": null,
"rubric": {},
"knockout_questions": [],
"created_at": "2026-07-10T09:41:12.000Z"
},
"run_id": "0c9be9a4-2b77-4e19-8a5d-f21e6b40c7d3",
"replayed": false
}The run writes description_md (and description_ar_md when bilingual), SEO metadata, JSON-LD, suggested knockout questions, and the screening rubric onto the job. With an Idempotency-Key header, a repeat submission returns the original job with 200 and replayed: true.
List and retrieve#
/v1/jobs| Query | Type | Description | |
|---|---|---|---|
| status | enum | optional | draft · published · paused · closed · filled |
| limit | integer | default: 20 | Capped at 50. Newest first. |
/v1/jobs/{id}The detail read includes the full JD (description_md, description_ar_md), rubric, knockout_questions, jd_meta, and counts (applications, screenings).
Edit a job#
/v1/jobs/{id}| Field | Type | Description | |
|---|---|---|---|
| description_md | string | optional | Replace the English JD markdown. |
| rubric | object | optional | {criteria: [{id, name, description, weight}]} — 1–20 criteria, weight is an integer 1–10, normalized at scoring time. See Screening for how weights drive the ranking. |
| knockout_questions | array | optional | [{id, question, type, disqualifyOn}] — evaluated inline at apply time, no AI involved. type: boolean · text · number. |
| closes_at | string | null | optional | ISO 8601 closing date (JobPosting validThrough). null clears it. |
curl -X PATCH https://hire.whizztech.ai/v1/jobs/4d1a8f36-9e02-47b8-b7c4-3a92d5e60f18 \
-H "Authorization: Bearer $HIRE_KEY" \
-H "Content-Type: application/json" \
-d '{
"rubric": {
"criteria": [
{ "id": "fleet", "name": "Fleet management experience",
"description": "Managed 50+ vehicle fleets", "weight": 5 },
{ "id": "systems", "name": "Systems (SAP/TMS)",
"description": "Hands-on ERP/TMS usage", "weight": 3 },
{ "id": "leadership", "name": "Team leadership",
"description": "Led ops teams of 5+", "weight": 2 }
]
},
"closes_at": "2026-09-30T23:59:59Z"
}'Publish#
/v1/jobs/{id}/publishSets the job live and starts a free distribute run: hosted career page, Google for Jobs JSON-LD, and the board feeds. Publishing counts against your plan's active-job limit; exceeding it fails without side effects:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"code": "job_limit",
"message": "Your free plan allows 1 active job post. Close or pause a job, or upgrade your plan."
}
}Screen#
/v1/jobs/{id}/screenScreens every eligible CV against the rubric and returns a screening_id + run_id. Body: { k, mode }. Fully documented on the Screening page.
Applications#
/v1/jobs/{id}/applications| Query | Type | Description | |
|---|---|---|---|
| status | enum | optional | new · screening · shortlisted · in_review · interview · offer · hired · rejected · withdrawn |
| limit | integer | default: 50 | Capped at 100. Newest first. |
{
"object": "list",
"data": [
{
"id": "e2c81f47-0a95-4d36-b8e1-6f24a0d7c593",
"object": "application",
"status": "new",
"source": "career_page",
"knockout_passed": true,
"cv_file_id": "7f3a2d15-9e60-4b8c-a4f7-02c9d6e18b54",
"candidate": {
"id": "1b7d4e90-3c58-4f2a-96d0-84b5e1a2c766",
"full_name": "Omar Haddad",
"email": "omar@example.com",
"phone": "+971501234567",
"location": "Dubai"
},
"latest_screening": {
"screening_id": "8a1c5e72-3f90-4b6d-a2e8-51c7d0b94f36",
"score": 86.5,
"verdict": "strong",
"rank": 1,
"in_top_k": true
},
"created_at": "2026-07-08T14:22:05.000Z"
}
]
}latest_screeningcarries each candidate's result from the most recent screening of this job (null before the first screening or for unscreened applications).
Bulk CV intake#
/v1/cvsAttach up to 10 base64-encoded CVs (.pdf or .docx, ≤10 MB decoded each) to a job — each becomes a candidate + application with source import. Free: parsing and scoring happen during screening. Returns 201 with the created application_ids.
curl -X POST https://hire.whizztech.ai/v1/cvs \
-H "Authorization: Bearer $HIRE_KEY" \
-H "Content-Type: application/json" \
-d '{
"job_id": "4d1a8f36-9e02-47b8-b7c4-3a92d5e60f18",
"files": [
{ "filename": "omar-haddad.pdf", "content_base64": "JVBERi0xLjQK…" },
{ "filename": "sara-aly.docx", "content_base64": "UEsDBBQABgAI…" }
]
}'Runs#
/v1/runs/{id}Every asynchronous operation — jd_generate, screen_batch, interview_kit, distribute — is a run with live per-stage progress. Poll with backoff (1.5s growing toward 10s) or use webhooks. Failed runs refund their credits automatically.
{
"id": "0c9be9a4-2b77-4e19-8a5d-f21e6b40c7d3",
"object": "run",
"type": "jd_generate",
"status": "succeeded",
"stage": "finalize",
"stages": [
{ "key": "compose", "label": "Composing the job description", "status": "done" },
{ "key": "arabic", "label": "Arabic (MSA) version", "status": "done" },
{ "key": "rubric", "label": "Screening rubric & knockouts", "status": "done" },
{ "key": "finalize", "label": "SEO meta & JSON-LD", "status": "done" }
],
"result": { "job_post_id": "4d1a8f36-9e02-47b8-b7c4-3a92d5e60f18" },
"error": null,
"credits_charged": 0,
"created_at": "2026-07-10T09:41:12.000Z",
"finished_at": "2026-07-10T09:42:38.000Z"
}| Field | Type | Description |
|---|---|---|
| status | enum | queued → processing → succeeded | failed | canceled. |
| stages | array | Pipeline stages with per-stage status and timestamps — render progress bars from this. |
| result | object | Type-specific on success: jd_generate {job_post_id} · screen_batch {screening_id, screened} · interview_kit {kit_id} · distribute {channels}. |
| credits_charged | integer | What this run debited (0 for free runs). Refunded if the run fails. |