> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instaview.sk/llms.txt
> Use this file to discover all available pages before exploring further.

# Interviews

> Schedule and manage AI-powered interviews with the Interviews API

## 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

```json theme={null}
{
  "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

| Operation           | Required Scope      | Additional                       |
| ------------------- | ------------------- | -------------------------------- |
| List interviews     | `read:interviews`   | `read:candidates`, `read:agents` |
| Get interview by ID | `read:interviews`   |                                  |
| Create interview    | `write:interviews`  | `read:candidates`, `read:agents` |
| Delete interview    | `delete:interviews` |                                  |

## Creating Interviews

### With Existing Candidate and Agent

```javascript theme={null}
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.
  }),
});
```

<Info>
  **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.
</Info>

### 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:**

```javascript theme={null}
const interview = await createInterview({
  candidate: {
    jobId: "job-uuid",
    firstName: "Jane",
    lastName: "Doe",
    email: "jane@example.com",
    phoneNumber: "+1234567890",
    gdprExpiryDate: "2026-11-16",
  },
  agentId: "agent-uuid",
  scheduleTime: "2024-01-20T14:00:00Z",
});
```

**Without Job Association (Candidate Pool):**

```javascript theme={null}
const interview = await createInterview({
  candidate: {
    firstName: "John",
    lastName: "Smith",
    email: "john@example.com",
    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",
});
```

<Info>
  **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](/api-reference/candidates/update-candidate).
</Info>

### 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.

```javascript theme={null}
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",
});
```

<Info>
  **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.
</Info>

<Info>
  **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).
</Info>

### 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:

```javascript theme={null}
const interview = await createInterview({
  candidate: {
    firstName: "Jane",
    lastName: "Doe",
    email: "jane@example.com",
    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",
});
```

<Info>
  **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
</Info>

<Info>
  **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.
</Info>

### Scheduling

<Warning>
  **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.
</Warning>

The `scheduleTime` field is optional. Omit it to start the interview immediately, or provide a future timestamp to schedule it.

```javascript theme={null}
// 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.

```javascript theme={null}
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
}
```

<Info>
  Deleting an interview removes it from list and get operations. The interview will no longer appear in API queries.
</Info>

## Interview Status

<Tabs>
  <Tab title="scheduled">
    Waiting for start time - Interview is scheduled for future - Reminders will
    be sent
  </Tab>

  <Tab title="in_progress">
    Currently happening - Candidate is being interviewed - AI agent is active
  </Tab>

  <Tab title="completed">
    Successfully finished - Interview ended normally - Analysis available -
    Transcript and recording ready
  </Tab>

  <Tab title="cancelled">
    Cancelled before starting - Never took place - No recording or analysis
  </Tab>

  <Tab title="failed">
    Technical failure - System error occurred - May need to reschedule
  </Tab>
</Tabs>

## Retrieving Results

### Get Interview with Analysis

```javascript theme={null}
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

```javascript theme={null}
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

| Field              | Type      | Description                                                             |
| ------------------ | --------- | ----------------------------------------------------------------------- |
| `overallRating`    | number    | Overall rating (0-100)                                                  |
| `companyFitRating` | string    | Company fit: `UNDEFINED`, `LOW`, `MEDIUM`, `HIGH`                       |
| `education`        | string    | Education level (see enum values below)                                 |
| `experience`       | string    | Experience level (see enum values below)                                |
| `strongPoints`     | string\[] | Candidate's strong points and advantages                                |
| `weakPoints`       | string\[] | Areas for improvement                                                   |
| `evaluation`       | string\[] | Overall evaluation summary and recommendations                          |
| `status`           | number    | Analysis status: `1`=PENDING, `2`=PROCESSING, `3`=COMPLETED, `4`=FAILED |
| `createdAt`        | string    | ISO 8601 timestamp                                                      |
| `updatedAt`        | string    | ISO 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`

```javascript theme={null}
{
  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:

<Tabs>
  <Tab title="SCREENING">
    **Standard candidate screening interview**

    Used for evaluating candidates against job requirements. The analysis uses only the `general` fields—there is no `specific` data.

    ```json theme={null}
    {
      "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
      }
    }
    ```
  </Tab>

  <Tab title="OUTREACH">
    **Recruitment outreach calls**

    Used for initial candidate outreach to gauge interest. The `specific` field contains outreach-specific data:

    | Field               | Type   | Description                             |
    | ------------------- | ------ | --------------------------------------- |
    | `interestType`      | string | Candidate's interest level              |
    | `specificFeedback`  | string | Detailed feedback from the candidate    |
    | `preferredNextStep` | string | Candidate's preferred next action       |
    | `rescheduleTime`    | number | Preferred callback time (if applicable) |

    ```json theme={null}
    {
      "analysis": {
        "id": "analysis-uuid",
        "general": {
          "overallRating": 75,
          "companyFitRating": "MEDIUM",
          "strongPoints": ["Interested in the role", "Available immediately"],
          "weakPoints": ["Salary expectations may be high"],
          "evaluation": ["Schedule follow-up interview"],
          "status": 3,
          "createdAt": "2024-01-20T14:30:00Z",
          "updatedAt": "2024-01-20T14:30:00Z"
        },
        "specific": {
          "interestType": "INTERESTED",
          "specificFeedback": "Candidate expressed strong interest in the backend role",
          "preferredNextStep": "Technical interview next week"
        }
      }
    }
    ```
  </Tab>

  <Tab title="GENERIC">
    **Jobless interviews (no job assignment required)**

    Used for interviews where candidates don't need to be assigned to a specific job. Uses the same analysis structure as OUTREACH:

    | Field               | Type   | Description                             |
    | ------------------- | ------ | --------------------------------------- |
    | `interestType`      | string | Candidate's interest level              |
    | `specificFeedback`  | string | Detailed feedback from the candidate    |
    | `preferredNextStep` | string | Candidate's preferred next action       |
    | `rescheduleTime`    | number | Preferred callback time (if applicable) |

    ```json theme={null}
    {
      "analysis": {
        "id": "analysis-uuid",
        "general": {
          "overallRating": 70,
          "companyFitRating": "MEDIUM",
          "strongPoints": ["Open to opportunities"],
          "weakPoints": ["Not actively looking"],
          "evaluation": ["Add to talent pool for future positions"],
          "status": 3,
          "createdAt": "2024-01-20T14:30:00Z",
          "updatedAt": "2024-01-20T14:30:00Z"
        },
        "specific": {
          "interestType": "CALLBACK_REQUESTED",
          "specificFeedback": "Prefers to be contacted in Q2",
          "preferredNextStep": "Follow up in 3 months"
        }
      }
    }
    ```
  </Tab>

  <Tab title="LANGUAGE_TEST">
    **Language proficiency assessment**

    Used for evaluating candidate language skills using CEFR standards. The `specific` field contains detailed language assessment data:

    | Field                     | Type   | Description                                               |
    | ------------------------- | ------ | --------------------------------------------------------- |
    | `pronunciationScores`     | object | Pronunciation metrics (accuracy, fluency, prosody: 50-95) |
    | `pronunciationAssessment` | object | CEFR pronunciation level (A1-C2) with reasoning           |
    | `grammar`                 | object | Grammar assessment with CEFR level and summary            |
    | `vocabulary`              | object | Vocabulary assessment with CEFR level and summary         |
    | `overallScore`            | object | Combined CEFR level with confidence score                 |
    | `combinedCefrEvaluation`  | object | Final CEFR evaluation with confidence and summary         |

    ```json theme={null}
    {
      "analysis": {
        "id": "analysis-uuid",
        "general": {
          "overallRating": 82,
          "companyFitRating": "HIGH",
          "strongPoints": ["Fluent speaker", "Good vocabulary range"],
          "weakPoints": ["Minor grammatical errors"],
          "evaluation": ["Meets B2 requirement for the position"],
          "status": 3,
          "createdAt": "2024-01-20T14:30:00Z",
          "updatedAt": "2024-01-20T14:30:00Z"
        },
        "specific": {
          "pronunciationScores": {
            "accuracy": 85,
            "fluency": 88,
            "prosody": 82
          },
          "pronunciationAssessment": {
            "estimated_pronunciation_level": "B2",
            "reasoning": "Clear articulation with occasional non-native patterns"
          },
          "grammar": {
            "level": "B2",
            "meets_tested_level": true,
            "summary": "Consistent use of complex structures with minor errors"
          },
          "vocabulary": {
            "level": "C1",
            "meets_tested_level": true,
            "summary": "Rich vocabulary with appropriate professional terminology"
          },
          "overallScore": {
            "level": "B2",
            "confidence": 0.85,
            "summary": "Strong B2 level with elements of C1 vocabulary"
          },
          "combinedCefrEvaluation": {
            "final_level": "B2",
            "confidence": 0.87,
            "summary": "Candidate demonstrates solid B2 proficiency"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Best Practices

<CardGroup cols={2}>
  <Card title="Check Billing" icon="credit-card">
    Verify billing limits before bulk scheduling
  </Card>

  <Card title="Set Realistic Times" icon="clock">
    Schedule with buffer time for candidate convenience
  </Card>

  <Card title="Monitor Status" icon="signal">
    Poll interview status for real-time updates
  </Card>

  <Card title="Store Analysis" icon="database">
    Save analysis data to your database
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Agents" icon="robot" href="/guides/resources/agents">
    Create and configure AI interview agents
  </Card>

  <Card title="Candidates" icon="user" href="/guides/resources/candidates">
    Learn about candidate management
  </Card>

  <Card title="Delete Interview" icon="trash" href="/api-reference/interviews/delete-interview">
    Learn about soft-deleting interviews
  </Card>

  <Card title="Billing" icon="dollar-sign" href="/guides/resources/billing">
    Understand interview costs and limits
  </Card>
</CardGroup>
