Lifecycle¶
Every interview moves through three phases described in the following diagram.
┌──────────────┐ ┌──────────────────┐ ┌─────────────┐
│ YOUR APP │ │ Allps API │ │ CANDIDATE │
└──────┬───────┘ └────────┬─────────┘ └──────┬──────┘
│ │ │
│ PHASE 1 — SCHEDULE │ │
│ │ │
│ POST /interview/ │ │
│ create-from-questions │ │
├────────────────────────►│ │
│ │ │
│ │ • Persist record │
│ │ • Generate questions │
│ │ • Hash payload │
│ │ │
│◄────────────────────────┤ │
│ { interview_id, │ │
│ interview_link } │ │
│ │ │
│ │ │
│ PHASE 2 — DELIVERY (out-of-band) │
│ │ │
│ interview_link │ │
├───────────────────────────────────────────────────►
│ │ │
│ │ Candidate opens link, │
│ │ grants mic access │
│ │◄───────────────────────►│
│ │ │
│ │ Live AI-led interview │
│ │ (audio / video stream) │
│ │◄───────────────────────►│
│ │ │
│ │ • Persist transcript │
│ │ • Persist evaluation │
│ │ • Persist media │
│ │ │
│ │ │
│ PHASE 3 — RETRIEVE │ │
│ │ │
│ GET /interview/ │ │
│ details/{id} │ │
├────────────────────────►│ │
│◄────────────────────────┤ │
│ state = 2 (ENDED) │ │
│ │ │
│ GET /interview/ │ │
│ transcript/{id} │ │
├────────────────────────►│ │
│◄────────────────────────┤ │
│ │ │
│ GET /interview/ │ │
│ evaluation-report/{id} │ │
├────────────────────────►│ │
│◄────────────────────────┤ │
│ │ │
Phase 1 — Scheduling an interview¶
Three create endpoints cover the three kinds of interview the platform supports.
| Endpoint | Interview kind | Evaluation shape |
|---|---|---|
POST /interview/create-from-questions |
Job/Skill interview | Per-question rating + LLM overall summary. |
POST /interview/screening/create-from-questions |
Screening interview | Boolean qualifying outcomes + communication analysis. |
POST /interview/create-from-questions with interview_type: 2 |
Video introduction | No evaluation; media hand-off only. |
These endpoints return an interview_id and an
interview_link.
1.1 Job interview from structured questions¶
{
"job_title": "Senior Backend Engineer",
"candidate_id": "0f2b8c6e-4c9b-4d1a-9b2f-0f2b8c6e4c9b",
"language_code": 1,
"experience_level": "senior",
"difficulty_level": "medium",
"primary_tech_focus": "Distributed Systems",
"questions": [
{
"question": "Walk me through how you would design a rate limiter.",
"evaluation_criteria": [
"Mentions token bucket or sliding window",
"Discusses distributed state (Redis, etc.)",
"Considers burst vs sustained traffic"
],
"sample_answer": "A token bucket with a Redis-backed counter is common…",
"type": "technical"
}
]
}
Field reference — CreateInterviewFromQuestionsRequest
| Field | Type | Required | Notes |
|---|---|---|---|
job_title |
string | yes | Displayed to the candidate. |
candidate_id |
string | yes | Your internal ID. Echoed back on every read so you can correlate. |
language_code |
integer | no (default 1) |
Language Allps speaks and evaluates in. See AgentLanguages. |
questions |
array of SkillInterviewQuestion |
yes | The question list. |
questions[].question |
string | yes | The literal question text. |
questions[].evaluation_criteria |
string[] | yes | What "good" looks like. Give the LLM concrete, checkable bullets. |
questions[].sample_answer |
string | null | no | Optional model answer the evaluator can reference. |
questions[].type |
"technical" | "behavioral" | "situational" |
no (default "technical") |
Governs the evaluator's rubric. |
experience_level |
"junior" | "senior" | "assistant" | "intern" |
no (default "junior") |
Calibrates follow-up difficulty. |
difficulty_level |
"easy" | "medium" | "hard" |
no (default "easy") |
Further tunes question selection. |
primary_tech_focus |
string | yes | Free-text domain label used in prompts. |
1.2 Screening interview from structured questions¶
Screening interviews have a different evaluation process. Every question is either graded against explicit criteria
(qualifying) or recorded without grading (information). The response
also includes a communication analysis (filler words, repetition, clarity).
{
"job_title": "Customer Support Lead",
"candidate_id": "0f2b8c6e-4c9b-4d1a-9b2f-0f2b8c6e4c9b",
"interview_lang_code": 1,
"questions": [
{
"question_text": "Are you legally authorized to work in the EU?",
"question_type": "qualifying",
"asking_order": 1,
"qualifying_criteria": "A clear yes/no answer. 'Yes' is the expected outcome."
},
{
"question_text": "What is your current notice period?",
"question_type": "information",
"asking_order": 2,
"qualifying_criteria": null
}
]
}
Field reference — ScreeningQuestionSchema
| Field | Type | Required | Notes |
|---|---|---|---|
question_text |
string | yes | Question text. |
question_type |
"qualifying" | "information" |
yes | Qualifying questions are graded. Information questions are only recorded. |
asking_order |
integer | yes | Position in the interview. Use 1, 2, 3, … |
qualifying_criteria |
string | null | yes (may be null) | Grading rubric for qualifying questions. Ignored for information questions. |
Language field name
The screening endpoint takes interview_lang_code, not language_code.
The values are the same
(AgentLanguages).
1.3 Resetting an interview¶
Development and staging only. Wipes the transcript, evaluation, state details and any local media so the same interview can be retaken.
In production, this endpoint returns OperationNotPermittedException.
No idempotency on create
Create endpoints are not idempotent. If you retry a create after a network timeout you may create a duplicate interview. See Idempotency for the recommended retry strategy.
Phase 2 — The candidate experience¶
This phase happens entirely on Allps.
2.1 What the candidate sees¶
- The candidate opens
/interview?iid=…. - The AI greets them, asks for a self-introduction, and walks through the question set — adapting follow-ups based on their answers.
- When all questions are asked, interview is concluded.
2.2 Constraints to communicate¶
Important information for the candidates
These constraints trip up some candidates who aren't informed ahead of time. Put a one-line note next to the link when you send it.
- One active session per interview. If the interview is already open in
another tab or device, the new connection is rejected with an
INTERVIEW_NOT_ALLOWEDevent. The candidate must close the old session first. - Microphone permission is required. Allps cannot conduct the interview without it.
- Interruptions are tolerated for a limited grace period. If the candidate
disconnects and returns, their state is preserved for maximum of 15 minutes. After that,
the interview is terminated with reason masked as
user-inactivity.
Phase 3 — Retrieving results¶
Once the candidate finishes, the interview record transitions to state == 2
(ENDED). You then have two choices: poll the read endpoints, or register
a webhook and have results pushed to you.
Recommended only if you have a small number of interviews or want to avoid owning a receiver.
- Call
GET /interview/details/{id}every 30–60 seconds. - Stop when
state == 2. - Fetch the evaluation report. If it returns
404 InterviewNotEndException, wait 30 seconds and try again — the report is generated asynchronously and may lag a few seconds behind the state transition. - Fetch the transcript. Recordings may be delayed further — they are remuxed and uploaded to cloud storage in the background.
Backoff: 30 s interval for the first 10 minutes, then 5 minutes for up to 24 hours, then give up.
Recommended for production. See the Webhooks page for the full setup, but the short version is:
POST /webhooks/endpointswith your receiver URL.- Store the one-time
secretfrom the response. - Verify the
X-Webhook-Signatureheader on every delivery. - The
interview.media_processedevent carries the transcript, the evaluation, and the recording URLs in a single payload.
3.1 Available artefacts¶
| Artefact | Endpoint | Notes |
|---|---|---|
| Interview metadata | GET /interview/details/{id} |
State, timing, language, ending reason. |
| Full transcript | GET /interview/transcript/{id} |
Ordered list of turns with role and timestamp. |
| Question-level evaluation | GET /interview/evaluation-report/{id} |
Short form for job interviews; long form for screening/video-intro. |
| Overall summary | GET /interview/overall-evaluation-report/{id} |
Suitability verdict with strengths, weaknesses, recommendations. |
| Audio recording | GET /interview/get-recording/{id} |
MP3, mixed candidate + agent audio. |
| Video recording | GET /interview/get-video-recording/{id} |
WebM with video and mixed audio. |
| System logs | GET /interview/get-logs/{id} |
Debug logs. Mostly for Allps support. |
3.2 Reading the interview record¶
GET /interview/details/{interview_id} returns an InterviewDetailsResponse.
The fields you'll use most often:
| Field | Meaning |
|---|---|
id |
The interview_id you're already tracking. |
state |
Runtime state — see InterviewState. |
ending_reason |
Why the interview ended — see EndingReason. |
language_code |
Language Allps conducted the interview in. |
interview_type |
Numeric type code — see InterviewTypes. |
archival_status |
Whether the recordings have been processed and uploaded. |
created_at |
Timestamp of interview creation. |
allpsai_interview_id |
Upstream id when the interview originated from the Talent platform. |
3.3 Reading the transcript¶
GET /interview/transcript/{interview_id} returns an
InterviewTranscriptResponse:
{
"transcript": [
{
"role": "assistant",
"content": "Hello! I'm Allps, your AI interviewer for today. Welcome!",
"created_at": "2025-01-15T10:00:01.234Z",
"control_id": "procedural",
"video_time": { "begin": 0, "end": 8, "formatted": "00:00 - 00:08" }
},
{
"role": "user",
"content": "Hi, thanks for having me. I'm a backend engineer with about eight years of experience.",
"created_at": "2025-01-15T10:00:22.101Z",
"control_id": "procedural",
"video_time": { "begin": 8, "end": 27, "formatted": "00:08 - 00:27" }
}
]
}
roleis"user"(the candidate) or"assistant"(the AI).control_idlinks each turn to the specific question it belongs to (matching the ids used in the evaluation report). Turns withcontrol_id = "procedural"are greetings, transitions, or acknowledgements that aren't scored.video_timegives begin/end offsets in seconds — use it to deep-link a video player directly to a turn.
3.4 Reading the evaluation¶
The response shape depends on interview_type.
Returns an OverallEvaluation — the short form:
{
"overall_assessment": {
"suitability": "Meets expectations",
"strengths": [
"Strong grasp of distributed systems fundamentals",
"Clear, structured communication"
],
"weaknesses": [
"Limited exposure to large-scale data pipelines"
],
"recommendations": [
"Probe deeper on data engineering experience in a follow-up round"
]
}
}
suitability is always returned in English, so you can safely switch on it
regardless of the interview language. Values are enumerated in
Suitability.
Returns an InterviewEvaluationReportResponse — the full report:
{
"id": "…",
"interview": "…",
"user": "…",
"evaluation_report": { "questions": [ /* … */ ] },
"overall_evaluation": null,
"video_analysis_report": null,
"comm_analysis_report": { /* … */ },
"created_at": "2025-01-15T10:05:00Z"
}
The per-question breakdown lives under evaluation_report.questions. Each
entry matches the EvaluatedQuestion schema in the
API Reference.
3.5 Reading the overall summary¶
GET /interview/overall-evaluation-report/{interview_id} always returns the
short OverallEvaluation form, regardless of interview_type. Use it when you
only need the verdict and don't want to branch on interview kind.
3.6 Recordings¶
Do not persist the recording URL
The presigned URL is short-lived (typically one hour). Store the
interview_id, not the URL, and re-request when you need the file. If you
must archive the bytes, download them within the validity window.
If a recording isn't ready yet — the interview just ended, or archival is still
in progress — you may receive an HTTP 500 RecordingCreationException. Retry
with exponential backoff. Poll archival_status on the details endpoint if you
want to know when it's safe to fetch.