Skip to main content

Human interviews

Your interviewers and the candidate on one call, inside your own product.

A human_interview is a call between the candidate and people on your side, with no AI interviewer in it. It runs in the same embedded room as an ai_interview, and we record it, transcribe it and write it up.

GET /v1/assessment-types lists it with its credit cost. It needs the Instant Meetings module on your organization, which is on unless it has been turned off.

Create one

curl -X POST https://hiring-api.experthire.cloud/v1/assessments \
  -H "Authorization: Bearer $EH_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "human_interview",
    "job_id": "'$JOB_ID'",
    "candidate": { "email": "[email protected]", "name": "Jane Doe" },
    "duration_minutes": 45,
    "interviewers": [
      { "name": "Priya Shah", "external_id": "client-user-17" },
      { "name": "Sam Lee", "email": "[email protected]" }
    ]
  }'

Still a placeholder: $EH_KEY, $JOB_ID. Add them under Your values above.

The response carries interviewers, each with the id you mint that person's session with.

  • duration_minutes is 5 to 240, and 60 if you leave it out. It is the booked length and the countdown shown in the room. Nobody is cut off when it runs out.
  • interviewers takes up to ten people. name is what the room and the transcript show. email is optional and only stops the same person being added twice. We never email an interviewer.
  • questions and send_invite are refused on this type.

A job can have as many human interviews as you need, for the same candidate or different ones.

Change the people later with:

CallWhat it does
GET /v1/assessments/{id}/interviewersEveryone on your side, with joined_at once they joined
POST /v1/assessments/{id}/interviewersAdd one, until the interview ends
DELETE /v1/assessments/{id}/interviewers/{interviewer_id}Remove one, and end their sessions

Set a time

This step is optional. POST /v1/assessments/{id}/schedule with start_at and time_zone books a slot, and calling it again reschedules. Each call emits interview.scheduled or interview.rescheduled. See scheduling.

The time is a booking, not a lock: anyone with a session can join early. An interview nobody joins is cancelled about an hour after its booked end, or seven days after creation if it was never booked. POST /v1/assessments/{id}/cancel withdraws it yourself and refunds the credit if nobody joined.

Put everyone in the room

Each person gets their own session. Mint the candidate's with the assessment alone, and each interviewer's with their interviewer_id:

# The candidate
curl -X POST https://hiring-api.experthire.cloud/v1/sessions \
  -H "Authorization: Bearer $EH_KEY" \
  -d '{"assessment_id": "'$ID'", "origin": "https://app.example.com"}'

# One interviewer
curl -X POST https://hiring-api.experthire.cloud/v1/sessions \
  -H "Authorization: Bearer $EH_KEY" \
  -d '{"assessment_id": "'$ID'", "origin": "https://app.example.com", "interviewer_id": "'$INTERVIEWER_ID'"}'

Still a placeholder: $EH_KEY, $INTERVIEWER_ID. Add them under Your values above.

Mount every session with the loader, exactly as in embedding. To send someone a hosted link instead, pass the same interviewer_id to POST /v1/assessments/{id}/launch-link.

How the call behaves:

  • Joining. Anyone can join while the interview is scheduled or in progress. The first person in starts it and, with a live key, starts recording everyone.
  • Leaving is not ending. Anyone can leave and rejoin. The room sends your page left when they do.
  • Ending. An interviewer's End for everyone closes every room, and each one sends your page interview.ended with endedBy. The candidate cannot end the interview. Your server can, with POST /v1/assessments/{id}/end and your secret key.
  • Abandoned calls. If everyone leaves without ending, we end the interview 15 minutes after the last room checked in. The room checks in every 30 seconds while it is open; if you build your own, poll GET /v1/assessments/{id}/timer to do the same. Any interview still open four hours after it started is ended too.
  • No pause. The countdown keeps running while people step away.

What you get back

When the interview ends:

  1. interview.ended fires.
  2. Each person's room transcribed their own microphone during the call. Those lines are put in order and saved, and interview.transcript_available fires.
  3. We write a summary of the interview. interview.summary_available fires, and GET /v1/assessments/{id}/report returns summary, interviewers, transcript_url and, on live, recording_url.
  4. On live, the interview is scored. interview.completed fires, and the report gains score, outcome, feedback and section_scores.

GET /v1/assessments/{id}/transcript labels each line Name [INTERVIEWER] or Name [CANDIDATE]. Labels come from the session, not from the browser, so nobody can speak under someone else's name. A person is not transcribed while their microphone is muted.

GET /v1/assessments/{id}/recording-url returns one video of the whole call.

We send no email

Nothing goes out for a human interview: no invitation, calendar invite, reminder or completion email, to the candidate or to your interviewers. Our hosted booking page refuses one too. You own every message.

Sandbox

A sandbox human interview is not recorded and not scored. The transcript and summary are real, because the rooms still transcribe, and the report comes back once the summary is written.

Limits

  • Up to ten interviewers per interview.
  • Four hours per call.
  • The embedded room has no shared code editor, whiteboard, chat or AI copilot for human interviews yet.

Next