Skip to main content

Reports

Reading a result, and what a score does and does not mean.

Fetch a report once the interview reaches Completed. Before that you get 404 report_not_ready naming the current status, rather than a report full of zeros that reads like a candidate who scored nothing:

curl https://prep-api.experthire.cloud/v1/interviews/$ID/report \
  -H "Authorization: Bearer $EH_SECRET_KEY"

Still a placeholder: $EH_SECRET_KEY. Add it under Your values above.

Fields

FieldNotes
overall_score0 to 100
summaryProse summary of how the interview went
feedbackScored dimensions, see below
main_questionThe coding or design prompt, when the round had one
codeThe candidate's final submission
mediaSigned URLs, see below
eventsProctoring signals, unordered. Sort by timestamp
duration_secondsActual time in the room, not the scheduled length
codeThe candidate's final submission, when the round had an editor
code_languageThe editor mode it was written in, when the client sent one

What is inside feedback

The keys are the same on every round type. Only the contents differ, so a non-coding round still carries a code_score object holding zeros.

KeyWhat it is
field_knowledgeSubject-matter judgement, score 0 to 100. The criteria are generated per transcript, so the names differ between candidates. Do not key a fixed rubric off them
speech_analysisFluency, Pronunciation, Grammar, Active Listening, Confidence. Note the key is rating, not score, and the scale starts at 1
behavioural_analysisPosture, derived from video, score 0 to 100. Eye Contact and Emotional State are withheld for institutions, see below
code_scoreZeros unless the round ran code. See below: zeros do not always mean nothing was written
num_speakers, num_faces_detected, off_platform_time, voice_verificationIntegrity signals, not grading

speech_analysis is judged from the transcript rather than measured from the audio, so it reflects what was transcribed. There is no words-per-minute or pause measurement.

An audio-only interview returns all three behavioural_analysis entries at score: 0 with outcome: "Not Analyzed (Audio Only)". That is a sentinel, not a candidate who never looked at the camera.

Institutions do not receive Eye Contact or Emotional State. Inferring emotion in an education institution is a prohibited practice under EU AI Act Art. 5(1)(f), so those two entries are removed from behavioural_analysis before the report leaves us. Posture is unaffected. Only a self-signup learner practising on their own account still receives them, and the same rule applies to the sandbox sample, so what you parse in sandbox is what you get on live. Do not treat a missing entry as a scoring failure.

Sandbox returns a sample, not a 404. Scoring runs off the recording and sandbox never records, so there is nothing to measure. Rather than leave you without a shape to parse, GET /v1/interviews/{id}/report answers with a sample report. It has the real shape, the real keys and the real scales, and carries "sample": true.

Its numbers are fixed placeholders that describe nobody. Gate on sample before showing a report to a user, and use a live key for real scores. The sample also carries the audio-only sentinel in behavioural_analysis, so handling it is part of what you can test in sandbox.

The transcript is unaffected: it is uploaded when the interview ends rather than by the scoring pipeline, so GET /v1/interviews/{id}/transcript returns the real thing in sandbox.

Two cautions:

  • audio_analysis, hiring_signal, anchor_insight and impact_indicators are present but always empty. Do not build against them.
  • voice_verification carries impostor and spoof verdicts. If you re-render feedback to a candidate or to your own client, allowlist the keys you want rather than passing the object through.

Treat feedback as additive: new keys can appear without a version change.

Zero code_score with code present

Before scoring, we check the submission is a genuine attempt at the question that was asked. A snippet that does not engage with it, a print("hello") left behind while testing the editor, scores 0 across the board with the reason "No code available for evaluation" even though code and code_analysis are populated.

So zeros mean one of two things: nothing was submitted, or what was submitted did not answer the question. Read code_analysis to tell them apart. It says outright when the submission was not a real attempt.

Media

media carries signed URLs valid for two hours:

{
  "recording_url": "https://...",
  "transcript_url": "https://...",
  "face_image_url": "https://...",
  "has_whiteboard": false
}

A field is absent when the artefact was never produced, which is normal: an interview that ended in the first minute has a transcript but no recording, and sandbox interviews are never recorded. Check for the field rather than assuming it is there.

Do not store these URLs. They expire. Store the interview id and re-fetch.

To refresh a recording link without pulling the whole report again:

curl https://prep-api.experthire.cloud/v1/interviews/$ID/recording-url \
  -H "Authorization: Bearer $EH_SECRET_KEY"

Still a placeholder: $EH_SECRET_KEY. Add it under Your values above.

Transcript

transcript_url above points at the raw stored file. If you would rather not parse our storage format, ask for it decoded:

curl https://prep-api.experthire.cloud/v1/interviews/$ID/transcript \
  -H "Authorization: Bearer $EH_SECRET_KEY"

Still a placeholder: $EH_SECRET_KEY. Add it under Your values above.

{
  "object": "list",
  "data": [
    { "at": "0:00:00", "speaker": "AGENT", "text": "Thanks for joining..." },
    { "at": "0:00:14", "speaker": "Ada [CANDIDATE]", "text": "Happy to be here." }
  ],
  "total_count": 2
}

at is an offset from the start of the recording, so it lines up with the video. Entries are in the order they were spoken.

Both this and recording-url return 404 until the interview finishes processing, with codes transcript_not_ready and recording_not_ready. Those mean retry later, not that the interview is missing. An interview where nobody spoke returns an empty list rather than an error.

What a score means

The score reflects one conversation, scored against the role you supplied. It is evidence, not a verdict.

Read it alongside the transcript, particularly when it is near a threshold you care about. The summary explains the reasoning; the number compresses it, and compression loses things.

A short interview is a weak signal. If duration_seconds is well under the round length, the candidate left early or hit a problem, and the score is built on less evidence than usual. Treat it accordingly.

Proctoring events

events lists what the candidate's browser reported: tab switches, pastes, multiple monitors.

An empty array means nothing was reported. It does not mean nothing happened. Browser proctoring reports signals, it does not enforce anything, and some signals require a permission the candidate can simply decline. Multiple-monitor detection is the clearest case: no permission, no signal, and absence is not evidence of a single screen.

Where the result carries real consequences, use the desktop app, which enforces at the operating system level rather than asking the browser nicely.