Skip to main content

Overview

The Interviews API enables you to schedule AI-powered interview sessions for your candidates. Each interview is conducted by an AI agent and produces detailed transcripts, recordings, and candidate analysis.

Resource Structure

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "candidateId": "candidate-uuid",
  "agentId": "agent-uuid",
  "status": "COMPLETED",
  "scheduledAt": "2024-01-20T14:00:00Z",
  "durationMinutes": 23,
  "finishedDate": "2024-01-20T14:25:30Z",
  "metadata": {
    "externalInterviewId": "INT-789"
  },
  "callAttempts": [
    {
      "id": "attempt-uuid",
      "direction": "OUTBOUND",
      "status": "COMPLETED",
      "scheduledAt": "2024-01-20T14:00:00Z",
      "calledAt": "2024-01-20T14:00:15Z",
      "duration": 1395,
      "recordingUrl": "https://storage.example.com/recordings/interview.mp3"
    }
  ],
  "analysis": {
    "id": "analysis-uuid",
    "general": {
      "overallRating": 85,
      "companyFitRating": "HIGH",
      "education": "MASTER_LEVEL",
      "experience": "THREE_TO_5_YEARS",
      "strongPoints": ["Strong technical skills", "Clear communication"],
      "weakPoints": ["Limited leadership experience"],
      "evaluation": ["Strong hire for senior individual contributor role"],
      "status": 3,
      "createdAt": "2024-01-20T14:30:00Z",
      "updatedAt": "2024-01-20T14:30:00Z"
    },
    "specific": null
  },
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-20T14:25:30Z"
}

Required Scopes

OperationRequired ScopeAdditional
List interviewsread:interviewsread:candidates, read:agents
Get interview by IDread:interviews
Create interviewwrite:interviewsread:candidates, read:agents
Delete interviewdelete:interviews

Creating Interviews

With Existing Candidate and Agent

const interview = await fetch("https://api.instaview.sk/interviews", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.INSTAVIEW_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    candidateId: "candidate-uuid",
    jobId: "job-uuid", // Optional: specify which job (required if candidate has multiple jobs). Alternatively, you can use `job` to define the job inline.
    agentId: "agent-uuid",
    scheduleTime: "2024-01-20T14:00:00Z", // Optional: scheduled time in ISO 8601 format (max 30 days in future). Omit for immediate start.
  }),
});
Job Selection: When using an existing candidateId, you can optionally specify jobId to indicate which job the interview is for. This is required when the candidate is associated with multiple jobs. The jobId must exist in the candidate’s job_ids array.

With Inline Candidate

Create an interview with a candidate that doesn’t exist yet. You can optionally associate the candidate with a job: With Job Association:
const interview = await createInterview({
  candidate: {
    jobId: "job-uuid",
    firstName: "Jane",
    lastName: "Doe",
    email: "[email protected]",
    phoneNumber: "+1234567890",
    gdprExpiryDate: "2026-11-16",
  },
  agentId: "agent-uuid",
  scheduleTime: "2024-01-20T14:00:00Z",
});
Without Job Association (Candidate Pool):
const interview = await createInterview({
  candidate: {
    firstName: "John",
    lastName: "Smith",
    email: "[email protected]",
    phoneNumber: "+1234567890",
    gdprExpiryDate: "2026-11-16",
    // jobId is optional - candidate will be created in your candidate pool
  },
  agentId: "agent-uuid",
  scheduleTime: "2024-01-20T14:00:00Z",
});
Inline Candidate Fields: The gdprExpiryDate field is required for inline candidates and must be a valid ISO 8601 date string representing when the candidate’s data will expire per GDPR. The jobId field is optional—omit it to add the candidate to your candidate pool without job association. You can assign them to jobs later using the update candidate endpoint.

With Inline Job (Existing Candidate)

Create an interview for an existing candidate while defining the job inline. This is useful when you know the job details but don’t want to create a separate job resource first.
const interview = await createInterview({
  candidateId: "candidate-uuid",
  job: {
    jobTitle: "Senior Backend Engineer",
    jobDescription: "We are looking for a senior engineer...",
    requiredSkills: ["TypeScript", "NestJS", "PostgreSQL"],
    niceToHaveSkills: ["Redis", "AWS"],
    languages: ["EN"],
    experience: "SENIOR",
    contractType: "FULL_TIME",
  },
  agentId: "agent-uuid",
  scheduleTime: "2024-01-20T14:00:00Z",
});
Inline Job Fields: - jobTitle is required and must be between 5–200 characters. - Arrays like requiredSkills and niceToHaveSkills accept up to 10 skills each; each skill is a non-empty string up to 128 characters. Combined total cannot exceed 10 skills. - Enum fields (such as languages, education, experience, contractType) use the same values as the Jobs API. - Nested objects location and salary reuse the core Job DTOs, so data stored is identical to jobs created via the Jobs API. The inline job is persisted as a regular Job entity during interview creation, and the interview is linked to this job.
XOR with jobId: - Use jobId when you already have a job created. - Use job when you want to define the job inline. - You must not send both jobId and job in the same request (XOR behavior).

With Inline Candidate and Inline Job

Create a complete interview with both candidate and job defined inline. This is the most streamlined approach when you have all the necessary information:
const interview = await createInterview({
  candidate: {
    firstName: "Jane",
    lastName: "Doe",
    email: "[email protected]",
    phoneNumber: "+1234567890",
    gdprExpiryDate: "2026-11-16",
  },
  job: {
    jobTitle: "Senior Backend Engineer",
    jobDescription: "We are looking for a senior engineer...",
    requiredSkills: ["TypeScript", "NestJS", "PostgreSQL"],
    niceToHaveSkills: ["Redis", "AWS"],
    languages: ["EN"],
    experience: "SENIOR",
    contractType: "FULL_TIME",
  },
  agentId: "agent-uuid",
  scheduleTime: "2024-01-20T14:00:00Z",
});
Complete Inline Workflow: When combining candidate with job: - A new Job entity is created in your company - A new Candidate entity is created and automatically linked to the new job - The Interview is associated with both the new candidate and job - All entities are persisted as permanent resources - This eliminates the need to create candidates or jobs separately before scheduling interviews
Job Specification Methods: You have multiple flexible ways to specify the job: 1. Inline job creation: Use job at the DTO level to define and create the job in one request 2. Existing job reference: Use jobId at the DTO level when you have a pre-existing job 3. Compact syntax: Use jobId within candidate for a more concise payload when creating a new candidate Priority order: If multiple sources are provided, job > DTO jobId > candidate.jobId Important: Do not combine candidate.jobId with DTO-level job fields (jobId or job) in the same request, as this creates ambiguity about which job to use.

Scheduling

Scheduling Constraint: The scheduleTime must be a valid ISO 8601 date-time string and cannot exceed 30 days in the future. Attempts to schedule beyond this limit will result in a 400 Bad Request error.
The scheduleTime field is optional. Omit it to start the interview immediately, or provide a future timestamp to schedule it.
// Immediate start (omit scheduleTime)
{
  candidateId: 'candidate-uuid',
  agentId: 'agent-uuid'
}

// Scheduled for later
{
  candidateId: 'candidate-uuid',
  agentId: 'agent-uuid',
  scheduleTime: '2024-01-20T14:00:00Z' // Optional: ISO 8601 format, max 30 days in future
}

Deleting Interviews

Interviews can be deleted to remove them from list and get operations.
async function deleteInterview(interviewId) {
  const response = await fetch(
    `https://api.instaview.sk/interviews/${interviewId}`,
    {
      method: "DELETE",
      headers: {
        Authorization: `Bearer ${process.env.INSTAVIEW_API_KEY}`,
      },
    }
  );

  const { data } = await response.json();
  return data; // Returns true on success
}
Deleting an interview removes it from list and get operations. The interview will no longer appear in API queries.

Interview Status

Waiting for start time - Interview is scheduled for future - Reminders will be sent

Retrieving Results

Get Interview with Analysis

async function getInterviewResults(interviewId) {
  const response = await fetch(
    `https://api.instaview.sk/interviews/${interviewId}`,
    { headers: { Authorization: `Bearer ${apiKey}` } }
  );

  const { data } = await response.json();

  return {
    status: data.status,
    durationMinutes: data.durationMinutes,
    finishedDate: data.finishedDate,
    overallRating: data.analysis?.general?.overallRating,
    strongPoints: data.analysis?.general?.strongPoints,
    weakPoints: data.analysis?.general?.weakPoints,
    evaluation: data.analysis?.general?.evaluation,
    specific: data.analysis?.specific,
  };
}

List Candidate’s Interviews

async function getCandidateInterviews(candidateId) {
  const response = await fetch(
    `https://api.instaview.sk/interviews?candidateId=${candidateId}`,
    { headers: { Authorization: `Bearer ${apiKey}` } }
  );

  return await response.json();
}

Analysis Structure

The analysis object provides comprehensive candidate evaluation. It contains a general object with overall assessment and an optional specific object for interview-type-specific data.

General Analysis Fields

FieldTypeDescription
overallRatingnumberOverall rating (0-100)
companyFitRatingstringCompany fit: UNDEFINED, LOW, MEDIUM, HIGH
educationstringEducation level (see enum values below)
experiencestringExperience level (see enum values below)
strongPointsstring[]Candidate’s strong points and advantages
weakPointsstring[]Areas for improvement
evaluationstring[]Overall evaluation summary and recommendations
statusnumberAnalysis status: 1=PENDING, 2=PROCESSING, 3=COMPLETED, 4=FAILED
createdAtstringISO 8601 timestamp
updatedAtstringISO 8601 timestamp
Education Level Values: UNDEFINED, PRIMARY_EDUCATION, SECONDARY_SCHOOL_STUDENT, SECONDARY_WITHOUT_DIPLOMA, SECONDARY_WITH_DIPLOMA, POST_SECONDARY_VOCATIONAL, UNIVERSITY_STUDENT, BACHELOR_LEVEL, MASTER_LEVEL, POSTGRADUATE Experience Level Values: UNDEFINED, NO_EXPERIENCE, LESS_THAN_1_YEAR, ONE_TO_3_YEARS, THREE_TO_5_YEARS, FIVE_TO_10_YEARS, TEN_TO_15_YEARS, MORE_THAN_15_YEARS
{
  analysis: {
    id: "analysis-uuid",
    general: {
      overallRating: 85,
      companyFitRating: "HIGH",
      education: "MASTER_LEVEL",
      experience: "THREE_TO_5_YEARS",
      strongPoints: [
        "Strong technical skills in React and Node.js",
        "Excellent problem-solving abilities"
      ],
      weakPoints: [
        "Limited experience with cloud infrastructure"
      ],
      evaluation: [
        "Strong hire for senior IC role",
        "Consider for team lead in 6-12 months"
      ],
      status: 3,
      createdAt: "2024-01-20T14:30:00Z",
      updatedAt: "2024-01-20T14:30:00Z"
    },
    specific: null // or interview-type-specific data
  }
}

Interview Types & Analysis

The specific field in the analysis contains interview-type-specific data based on the agent’s focus. There are four interview types:
Standard candidate screening interviewUsed for evaluating candidates against job requirements. The analysis uses only the general fields—there is no specific data.
{
  "analysis": {
    "id": "analysis-uuid",
    "general": {
      "overallRating": 85,
      "companyFitRating": "HIGH",
      "education": "MASTER_LEVEL",
      "experience": "THREE_TO_5_YEARS",
      "strongPoints": ["Strong technical background", "Good communication"],
      "weakPoints": ["Limited management experience"],
      "evaluation": ["Recommended for next round"],
      "status": 3,
      "createdAt": "2024-01-20T14:30:00Z",
      "updatedAt": "2024-01-20T14:30:00Z"
    },
    "specific": null
  }
}

Best Practices

Check Billing

Verify billing limits before bulk scheduling

Set Realistic Times

Schedule with buffer time for candidate convenience

Monitor Status

Poll interview status for real-time updates

Store Analysis

Save analysis data to your database

Next Steps