Skip to main content

Scheduling

Telling us when the candidate is expected.

curl -X POST https://hiring-api.experthire.cloud/v1/assessments/$ASSESSMENT_ID/schedule \
  -H "Authorization: Bearer $EH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"start_at": 1767225600, "time_zone": "Asia/Kolkata"}'

Still a placeholder: $ASSESSMENT_ID, $EH_SECRET_KEY. Add them under Your values above.

200Response
{
  "object": "assessment_schedule",
  "assessment_id": "3b8e1d02-5c77-4c2a-8a41-9b2f7e6d4c10",
  "status": "scheduled",
  "start_at": 1767225600,
  "end_at": 1767227400,
  "rescheduled": false,
  "reschedule_count": 0,
  "livemode": false
}

We record the start and derive the end from the assessment's length, including the intro buffer where one applies. time_zone is used in the candidate's reminders.

A new assessment is scheduled with no time set. The first time it gets is not a reschedule, whether you post it here or the candidate books it on the booking page. Calling this again after a time is set reschedules it.

Setting the time emits interview.scheduled, and each later change emits interview.rescheduled. Both fire whether the time came from this endpoint or from the candidate picking a slot on the booking page.

What we email the candidate

Three things, all from your own sending domain once one is verified, and all carrying your logo and brand colour. Roles created through the API send as your company, not as a person.

EmailWhenGoverned by
InviteOn create, only if you pass send_invitesend_invite on the create call
Booking confirmationWhen the candidate picks a time on the booking page, or when you set it with this endpointAlways sent from the booking page. From this endpoint, only if you passed send_invite on create
ReminderOnce, when the assessment is under 24 hours awayNothing. Always sent

None of these go out for a human_interview. We send nothing for one, and it cannot be booked on our booking page.

The booking confirmation carries an .ics, so the assessment lands on the candidate's calendar with the join link inside the entry. A reschedule sends an updated one. The reminder uses time_zone, so set it to the candidate's zone rather than yours.

The Email candidates by default setting in your dashboard governs only the invite the recruiter app sends when an interview is created. It does not stop booking confirmations or reminders, and it has no effect on this API at all: send_invite is the only control here.

Reminders only fire for an assessment with a booked time. One that nobody scheduled has nothing to remind against, and is swept as a no-show about seven days after creation. The sweep emits interview.cancelled and emails nobody: the candidate is not told they missed it.

The booking page, and why there is no slots endpoint

We host a candidate-facing booking page, but we do not publish availability. Those are different things, and the distinction decides what you build.

There is no endpoint that offers slots. But there is a candidate-facing booking page, hosted by us on your branded domain:

https://<your-domain>/schedule-call/{assessment_id}

The id is the one POST /v1/assessments returned, and the page is public: the id alone identifies the assessment, with no token to mint. The candidate picks a time, and gets the confirmation and calendar invite described above.

So you have two candidate journeys, and should pick one rather than sending both:

Launch linkBooking page
URLPOST /v1/assessments/{id}/launch-link/schedule-call/{id} on your domain
CandidateJoins immediatelyPicks a time, joins later
LifetimeSingle use, 7 days at mostRe-openable
Calendar inviteNoYes

A launch link does not redirect to the booking page. It opens the assessment.

There is deliberately no slots endpoint behind any of this. We do not model availability, and we check neither capacity, recruiter calendars nor conflicts, so offering slots would imply a guarantee that does not exist. The booking page lets the candidate choose a time; it does not promise anyone is free at it.

If you schedule from your own system instead, pick the time there and post the result to /schedule.

If you would rather not schedule at all

You do not have to. An assessment with a launch link works whenever the candidate opens it. Scheduling exists for the case where you want the time on record and reflected in the customer's dashboard and the candidate's reminders.

Rescheduling

Post to the same endpoint again with a new start_at. There is no separate reschedule call. It only counts as a reschedule once a time is already set, by you or by the candidate on the booking page. The response tells you it happened:

{
  "object": "assessment_schedule",
  "status": "scheduled",
  "start_at": 1748955600,
  "end_at": 1748957400,
  "rescheduled": true,
  "reschedule_count": 1
}

Cancelling

POST /v1/assessments/{id}/cancel withdraws it. Cancelling one that is already cancelled returns it unchanged, so retrying is safe.

The credit comes back only if the assessment was never taken, meaning it is still pending or scheduled and has no outcome. Once a candidate has attended, the work is done and there is nothing to return.

Resume screens

A resume_screen has no call to attend, so scheduling one returns unsupported_operation. Cancelling one works normally.

Next