Skip to main content

Async job status

Poll the status of an asynchronous job created by AI match jobs or AI score interview when called with "async": true.

Scope required: jobs:read

GET /api/v1/external/jobs/{job_id}
Authorization: Bearer sk_live_<key>

This endpoint counts towards the standard rate limit window (60 seconds).


Path parameters

ParameterDescription
job_idThe job_id returned in the async 202 Accepted response

Example request

curl "https://api.oikohire.com/api/v1/external/jobs/extjob_abc123" \
-H "Authorization: Bearer sk_live_<key>"

Response 200 OK — job in progress

{
"status": "success",
"data": {
"job_id": "extjob_abc123",
"type": "match_jobs",
"status": "queued",
"result": null,
"error": null,
"created_at": "2026-07-10T09:00:00.000Z",
"updated_at": "2026-07-10T09:00:01.000Z"
}
}

Response 200 OK — job completed

{
"status": "success",
"data": {
"job_id": "extjob_abc123",
"type": "match_jobs",
"status": "completed",
"result": {
"matches": [
{
"job_id": "clx9job123abc",
"title": "Senior Backend Engineer",
"match_score": 0.87,
"rationale": "Matches 7/8 skills: typescript, postgresql, nestjs",
"skills_gap": {
"matched": ["typescript", "postgresql"],
"missing": ["kubernetes"]
}
}
]
},
"error": null,
"created_at": "2026-07-10T09:00:00.000Z",
"updated_at": "2026-07-10T09:00:08.000Z"
}
}

Job status values

statusMeaning
queuedJob has been accepted and is waiting to be processed
processingJob is currently running
completedJob finished — result contains the payload
failedJob encountered an error — error contains the reason

Polling strategy

A simple exponential back-off pattern avoids hammering the endpoint while delivering results promptly:

async function pollJobResult(apiKey, jobId) {
const url = `https://api.oikohire.com/api/v1/external/jobs/${jobId}`;
const headers = { Authorization: `Bearer ${apiKey}` };
let delay = 1000; // start at 1 s

for (let attempt = 0; attempt < 12; attempt++) {
await new Promise((r) => setTimeout(r, delay));
const res = await fetch(url, { headers });
const body = await res.json();

if (body.data.status === 'completed') return body.data.result;
if (body.data.status === 'failed') throw new Error(body.data.error);

delay = Math.min(delay * 1.5, 15_000); // cap at 15 s
}

throw new Error('Job timed out after 12 attempts');
}

Job expiry

Async jobs are retained for 24 hours from creation. After that, polling the job ID returns 404 Not Found.

tip

For short transcripts or small resume texts, consider using the synchronous mode (omit "async": true) to avoid the overhead of polling.