TypeScript SDK.
@whizz/hire is a zero-dependency, fetch-based client for Node 18+, Bun, Deno, and edge runtimes — typed against the wire format exactly as the API returns it.
Install#
npm i @whizz/hireEnd-to-end example#
import { WhizzHire } from "@whizz/hire";
const hire = new WhizzHire({ apiKey: process.env.HIRE_KEY! });
// job → publish
const ack = await hire.jobs.create(
{
title: "Fleet Operations Manager",
seniority: "senior",
location: "Dubai, UAE",
skills: ["fleet management", "route optimization", "SAP"],
bilingual: true,
},
{ idempotencyKey: "fleet-ops-001" },
);
await hire.runs.waitFor(ack.run_id!, {
onProgress: (r) => console.log("stage:", r.stage),
});
await hire.jobs.publish(ack.job.id);
// screen every CV, get the top 5 with evidence
const screen = await hire.jobs.screen(ack.job.id, { k: 5 });
await hire.runs.waitFor(screen.run_id);
const screening = await hire.screenings.get(screen.screening_id, {
include: "results",
});
const top = screening.results!.filter((r) => r.in_top_k);
// interview kit for the front-runner
const kitAck = await hire.applications.interviewKit(top[0].application_id);
await hire.runs.waitFor(kitAck.run_id);
const kit = await hire.interviewKits.get(kitAck.kit_id);
console.log(kit.content.probes);Client surface#
| Field | Type | Description |
|---|---|---|
| hire.jobs | resource | create(params, {idempotencyKey}) · list({status, limit}) · get(id) · update(id, params) · publish(id) · screen(id, {k, mode}) · applications(id, {status, limit}). |
| hire.screenings | resource | get(id, {include: "results"}) — ranked results with criterion scores and evidence. |
| hire.applications | resource | interviewKit(applicationId, {language}) — 202 ack with kit_id + run_id. |
| hire.interviewKits | resource | get(id) — content fills in when the run succeeds. |
| hire.cvs | resource | upload({job_id, files}) — bulk base64 intake, ≤10 files. |
| hire.runs | resource | get(id) · waitFor(id, opts) — poll with backoff until terminal. |
| hire.usage | resource | get({days}) — balance + daily usage. |
| hire.webhooks | resource | create({url, events}) · list(). |
| verifyWebhookSignature | function | Standard Webhooks HMAC verification (Web Crypto — works on edge). |
runs.waitFor#
Polls a run until it reaches a terminal state, starting at 1.5s and backing off ~1.6× per poll toward a 10s ceiling. Resolves with the succeeded run; throws HireError with code run_failed, run_canceled, or poll_timeout (status 0) otherwise. Fully abortable:
const controller = new AbortController();
setTimeout(() => controller.abort(), 120_000); // hard 2-minute budget
const run = await hire.runs.waitFor(runId, {
signal: controller.signal,
pollMs: 2000,
timeoutMs: 600_000,
onProgress: (r) => console.log(r.stage),
});Errors & retries#
Every non-2xx response (after retries) throws a HireError carrying the error envelope. The client retries 429 and 5xx automatically (default 2 attempts), honoring retry-after; network failures retry with exponential backoff.
import { WhizzHire, HireError } from "@whizz/hire";
try {
await hire.jobs.publish(jobId);
} catch (err) {
if (err instanceof HireError) {
console.error(err.status, err.code, err.message);
// 403 job_limit "Your free plan allows 1 active job post. …"
if (err.code === "rate_limit_exceeded") {
console.log("retry after", err.retryAfter, "seconds");
}
}
}Webhook verification#
import { verifyWebhookSignature } from "@whizz/hire";
// in your webhook handler — payload must be the RAW body string
const ok = await verifyWebhookSignature(
rawBody,
{
"webhook-id": req.headers["webhook-id"],
"webhook-timestamp": req.headers["webhook-timestamp"],
"webhook-signature": req.headers["webhook-signature"],
},
process.env.HIRE_WEBHOOK_SECRET!, // whsec_…
);
if (!ok) return res.status(401).end();Constant-time comparison and a 5-minute replay tolerance (configurable via toleranceSeconds). The scheme itself is documented on the Webhooks page.
Options#
new WhizzHire({
apiKey: "wz_live_…", // required
baseUrl: "https://hire.whizztech.ai", // default
maxRetries: 2, // 429/5xx retries per request
fetch: customFetch, // instrumentation/testing
});