Screen a candidate
Updated
A screening is an AI interview built from one of your screening templates. The candidate takes it in their own time, and the findings come back to Orbit. Recruiters send screenings from Orbit. This page is for sending them from your own system, for example when a stage change in your ATS should invite the candidate without anyone opening Orbit.
What you need
- A key with the Screening scope, created in Orbit → Settings → API keys. It is a scope of its own: a key that reads or manages jobs answers
403here, and a screening key cannot read jobs. - A managed job ad. Screening is part of managing an ad, which a recruiter switches on in Orbit. On an ad that is not managed, the request answers
409withad_not_managed. - Three ids: the role’s
jobId, the candidate’s id on that role, and thetemplateIdof one of your active screening templates.
export ORBIT_SCREENING_KEY="…a key with the Screening scope…"
Invite the candidate
curl -X POST https://api.wipperoz.com/v1/jobs/job_01J8Z3K9Q0EXAMPLE/candidates/app_01J9B2C3D4EXAMPLE/screening \
-H "Authorization: Bearer $ORBIT_SCREENING_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tpl_01J9C3D4E5EXAMPLE",
"completeBy": "2026-10-02T00:00:00.000Z",
"message": "Thanks for applying. This takes about fifteen minutes.",
"language": "en"
}'
templateIdis the only required field. It must be one of your account’s active screening templates.completeByis the deadline, as an ISO 8601 date. Without it, the candidate has seven days.messageis a note the candidate reads in the invitation, up to 1,000 characters.languageisen,es,frorpt, andenby default. It is the language of the invitation email when the candidate is reached by email.
A field the route does not know answers 400, as on every write in this API.
{
"screening": {
"screeningId": "8d3f6a2e-4b1c-4f0a-9e7d-2c5b8a1f0e3d",
"jobId": "job_01J8Z3K9Q0EXAMPLE",
"candidateId": "app_01J9B2C3D4EXAMPLE",
"templateId": "tpl_01J9C3D4E5EXAMPLE",
"status": "invited",
"deliveryPath": "token",
"completeBy": "2026-10-02T00:00:00.000Z",
"requestedAt": "2026-09-25T01:10:00.000Z"
},
"billing": "overage",
"priceCents": 300,
"currency": "AUD"
}
deliveryPathsays how the candidate was reached, the same way Orbit reaches them:interviewis an interview request on their Virtual CV, andtokenis an email with a one-time link. Their email address is never returned.billingisincludedwhen the screening used one of the ad’s included screenings, andoveragewhen it is an extra one.priceCentsis the template’s price per screening, locked at this moment, in minor units and excluding GST. An extra screening is billed at that price only if the candidate completes it, so one they never take costs nothing.
Where the ids come from
jobIdis theidthe role got when you created it, or the oneGET /v1/jobsreturns to a key that reads jobs.- The candidate’s id is the one Orbit uses for them on that role. It is the last part of the address of their page in Orbit:
…/jobs/{jobId}/candidates/{candidateId}.
One screening at a time
A candidate has one screening per role at a time. While one is open, a second request is refused, and the refusal carries the open screening in error.screening, so your system can pick that one up instead of sending another invitation.
That also makes a retry after a timeout safe. If the first request went through, the retry is refused with the screening it created, and the candidate is invited once.
When it is refused
| Status | Code | What happened |
|---|---|---|
402 |
overage_cap_reached |
The screening is an extra one and would take the account past its monthly limit. The error carries priceCents, currency, capCents and spendCents. A billing admin can raise the limit in Orbit → Billing. |
409 |
ad_not_managed |
The ad is not managed. Managing it is done in Orbit. |
409 |
price_unavailable |
The template’s price could not be read. Try again shortly. |
400 |
bad_request |
The body is not valid, or there is no way to reach the candidate. |
403 |
forbidden |
The key does not carry the Screening scope, or the candidate was matched to the role rather than applying and has turned employer contact off. |
404 |
not_found |
The role or the candidate is not one of this account’s, or the template is not one of its active templates. |
429 |
rate_limited |
The candidate did not apply and has had as much unsolicited contact as they allow this week. |
A refused request sends nothing and leaves nothing reserved.
A 429 here is about the candidate, not your key, so retrying sooner does not help. The route is not under the per-minute rate limit and sends no X-RateLimit-* headers: one open screening per candidate per role, and the monthly limit on extra screenings, are what bound it.
Reference
triggerScreening