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

# Bulk Update Interviews

> Update multiple interviews in a single API call

## Overview

Batch-modify multiple interviews in a single API call. Useful for applying consistent settings across interviews, updating keywords in bulk, or cloning configuration from a template.

**Endpoint:** `PATCH /qsi/gather/interviews/bulk-update`

## Mode Behavior

The `mode` parameter controls how supplied values interact with existing data.

<Tabs>
  <Tab title="Overwrite">
    Supplied values **completely replace** existing values.

    For example, if an interview has keywords `["java", "python"]` and you send `keywords: ["go"]`, the interview will only have `["go"]` after the update.
  </Tab>

  <Tab title="Merge">
    Supplied values are **added to** existing values.

    Using the same example, if an interview has keywords `["java", "python"]` and you send `keywords: ["go"]`, the interview will have `["java", "python", "go"]` after the update.

    Use the `removed*` fields (`removedKeywords`, `removedQuestionIds`, `removedSurveyQuestionIds`, `removedAITextQuestionIds`) to selectively remove specific items without replacing the entire list.
  </Tab>
</Tabs>

## Parameters

<ParamField name="interviewIds" type="string[]" required>
  Array of interview UUIDs to update
</ParamField>

<ParamField name="mode" type="string" required>
  Update mode: `"overwrite"` or `"merge"`
</ParamField>

<AccordionGroup>
  <Accordion title="Interview Properties">
    <ParamField name="templateInterviewId" type="string">
      UUID of a template interview to clone settings from
    </ParamField>

    <ParamField name="title" type="string">
      Interview title
    </ParamField>

    <ParamField name="displayName" type="string">
      Display name shown to candidates
    </ParamField>

    <ParamField name="description" type="string">
      Interview description
    </ParamField>

    <ParamField name="language" type="string">
      Language code (e.g., `"en"`, `"es"`)
    </ParamField>

    <ParamField name="resume" type="boolean">
      Whether resume is required
    </ParamField>

    <ParamField name="webOnly" type="boolean">
      Web-only interview
    </ParamField>

    <ParamField name="descriptionUrl" type="string">
      URL to a job description
    </ParamField>

    <ParamField name="descriptionFileName" type="string">
      File name for the job description attachment
    </ParamField>

    <ParamField name="messageGroupId" type="string">
      UUID of message group
    </ParamField>

    <ParamField name="audioMessageId" type="string">
      UUID of an existing audio message
    </ParamField>

    <ParamField name="audioMessageTitle" type="string">
      Title for the custom audio message
    </ParamField>

    <ParamField name="audioMessageURL" type="string">
      URL of a custom audio message
    </ParamField>

    <ParamField name="knowledgeBaseIds" type="string[]">
      Array of knowledge base UUIDs to associate with the interviews
    </ParamField>
  </Accordion>

  <Accordion title="Questions">
    <ParamField name="audioQuestionAndMessageIds" type="string[]">
      Array of audio question and message UUIDs
    </ParamField>

    <ParamField name="surveyQuestions" type="object[]">
      Array of survey question objects. Each object contains:

      * `id` (string) — UUID of the survey question
      * `knockout` (boolean) — whether the question is a knockout question
    </ParamField>

    <ParamField name="removedQuestionIds" type="string[]">
      Array of audio question UUIDs to remove (useful in merge mode)
    </ParamField>

    <ParamField name="removedSurveyQuestionIds" type="string[]">
      Array of survey question UUIDs to remove (useful in merge mode)
    </ParamField>

    <ParamField name="removedAITextQuestionIds" type="string[]">
      Array of AI text question UUIDs to remove (useful in merge mode)
    </ParamField>
  </Accordion>

  <Accordion title="Keywords">
    <ParamField name="keywords" type="string[]">
      Array of keyword strings to add (merge mode) or set (overwrite mode)
    </ParamField>

    <ParamField name="removedKeywords" type="string[]">
      Array of keyword strings to remove (useful in merge mode)
    </ParamField>
  </Accordion>

  <Accordion title="Notifications and Scoring">
    <ParamField name="notificationSubscribers" type="string[]">
      Array of user UUIDs to receive notifications for these interviews
    </ParamField>

    <ParamField name="aiConfiguration" type="object">
      AI interview configuration object
    </ParamField>

    <ParamField name="scoreCardTopics" type="object[]">
      Array of score card topic objects. Each object contains:

      * `topic` (string) — name of the scoring topic
      * `weight` (number) — relative weight for this topic
      * `description` (string) — description of what this topic evaluates
      * `lookingFor` (string) — what the evaluator should look for
      * `scoreDescriptions` (object) — descriptions for each score level
    </ParamField>
  </Accordion>
</AccordionGroup>

## Response

<CodeGroup>
  ```json Success theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 3,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```

  ```json Partial Failure theme={null}
  {
    "data": {
      "success": false,
      "updatedCount": 2,
      "errors": [
        {
          "interviewId": "interview-uuid-3",
          "message": "Interview not found"
        }
      ],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

## Examples

### 1. Update Title and Display Name (Overwrite)

Set the same title and display name across multiple interviews.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X PATCH https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update \
      -H "x-api-key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{
        "interviewIds": ["int-uuid-1", "int-uuid-2", "int-uuid-3"],
        "mode": "overwrite",
        "title": "Senior Engineer Interview",
        "displayName": "Senior Engineer Phone Screen"
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch(
      'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
      {
        method: 'PATCH',
        headers: {
          'x-api-key': apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          interviewIds: ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
          mode: 'overwrite',
          title: 'Senior Engineer Interview',
          displayName: 'Senior Engineer Phone Screen'
        })
      }
    );
    const result = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    response = requests.patch(
        'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
        headers={
            'x-api-key': api_key,
            'Content-Type': 'application/json'
        },
        json={
            'interviewIds': ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
            'mode': 'overwrite',
            'title': 'Senior Engineer Interview',
            'displayName': 'Senior Engineer Phone Screen'
        }
    )
    result = response.json()
    ```
  </Tab>
</Tabs>

### 2. Add Keywords to Existing Interviews (Merge)

Add new keywords without removing existing ones.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2"],
    "mode": "merge",
    "keywords": ["remote", "senior", "full-stack"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 2,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 3. Replace All Keywords (Overwrite)

Completely replace the keywords on multiple interviews.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2"],
    "mode": "overwrite",
    "keywords": ["go", "kubernetes", "microservices"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 2,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 4. Remove Specific Keywords (Merge)

Remove specific keywords while keeping all others intact.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2", "int-uuid-3"],
    "mode": "merge",
    "removedKeywords": ["outdated-skill", "deprecated-tech"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 3,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 5. Clone from Template Interview (Overwrite)

Apply a template interview's configuration to multiple interviews.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X PATCH https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update \
      -H "x-api-key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{
        "interviewIds": ["int-uuid-1", "int-uuid-2", "int-uuid-3"],
        "mode": "overwrite",
        "templateInterviewId": "template-int-uuid"
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch(
      'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
      {
        method: 'PATCH',
        headers: {
          'x-api-key': apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          interviewIds: ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
          mode: 'overwrite',
          templateInterviewId: 'template-int-uuid'
        })
      }
    );
    const result = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    response = requests.patch(
        'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
        headers={
            'x-api-key': api_key,
            'Content-Type': 'application/json'
        },
        json={
            'interviewIds': ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
            'mode': 'overwrite',
            'templateInterviewId': 'template-int-uuid'
        }
    )
    result = response.json()
    ```
  </Tab>
</Tabs>

### 6. Add Survey Questions with Knockout (Merge)

Add survey questions to existing interviews, including knockout configuration.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2"],
    "mode": "merge",
    "surveyQuestions": [
      { "id": "sq-uuid-1", "knockout": false },
      { "id": "sq-uuid-2", "knockout": true }
    ]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 2,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 7. Remove Specific Questions (Merge)

Remove specific questions from interviews while preserving all others.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2"],
    "mode": "merge",
    "removedQuestionIds": ["q-uuid-old-1", "q-uuid-old-2"],
    "removedSurveyQuestionIds": ["sq-uuid-old-1"],
    "removedAITextQuestionIds": ["aitq-uuid-old-1"]
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 2,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 8. Set Score Card Topics (Overwrite)

Apply a standardized score card across multiple interviews.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X PATCH https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update \
      -H "x-api-key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{
        "interviewIds": ["int-uuid-1", "int-uuid-2"],
        "mode": "overwrite",
        "scoreCardTopics": [
          {
            "topic": "Technical Skills",
            "weight": 40,
            "description": "Evaluate depth of technical knowledge",
            "lookingFor": "Strong understanding of core concepts and practical experience",
            "scoreDescriptions": {
              "1": "No relevant technical knowledge",
              "2": "Basic understanding but limited experience",
              "3": "Solid knowledge with some practical experience",
              "4": "Strong expertise with extensive experience",
              "5": "Expert-level mastery with deep practical experience"
            }
          },
          {
            "topic": "Communication",
            "weight": 30,
            "description": "Evaluate clarity and effectiveness of communication",
            "lookingFor": "Clear, concise, and structured responses",
            "scoreDescriptions": {
              "1": "Unable to communicate ideas clearly",
              "2": "Somewhat clear but disorganized",
              "3": "Clear and reasonably well-structured",
              "4": "Very clear, well-structured, and engaging",
              "5": "Exceptionally clear, persuasive, and articulate"
            }
          },
          {
            "topic": "Problem Solving",
            "weight": 30,
            "description": "Evaluate approach to solving problems",
            "lookingFor": "Structured thinking and creative solutions",
            "scoreDescriptions": {
              "1": "No evidence of structured problem solving",
              "2": "Some structure but limited creativity",
              "3": "Good structured approach with reasonable solutions",
              "4": "Strong analytical thinking with creative solutions",
              "5": "Exceptional problem-solving with innovative approaches"
            }
          }
        ]
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch(
      'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
      {
        method: 'PATCH',
        headers: {
          'x-api-key': apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          interviewIds: ['int-uuid-1', 'int-uuid-2'],
          mode: 'overwrite',
          scoreCardTopics: [
            {
              topic: 'Technical Skills',
              weight: 40,
              description: 'Evaluate depth of technical knowledge',
              lookingFor: 'Strong understanding of core concepts and practical experience',
              scoreDescriptions: {
                '1': 'No relevant technical knowledge',
                '2': 'Basic understanding but limited experience',
                '3': 'Solid knowledge with some practical experience',
                '4': 'Strong expertise with extensive experience',
                '5': 'Expert-level mastery with deep practical experience'
              }
            },
            {
              topic: 'Communication',
              weight: 30,
              description: 'Evaluate clarity and effectiveness of communication',
              lookingFor: 'Clear, concise, and structured responses',
              scoreDescriptions: {
                '1': 'Unable to communicate ideas clearly',
                '2': 'Somewhat clear but disorganized',
                '3': 'Clear and reasonably well-structured',
                '4': 'Very clear, well-structured, and engaging',
                '5': 'Exceptionally clear, persuasive, and articulate'
              }
            },
            {
              topic: 'Problem Solving',
              weight: 30,
              description: 'Evaluate approach to solving problems',
              lookingFor: 'Structured thinking and creative solutions',
              scoreDescriptions: {
                '1': 'No evidence of structured problem solving',
                '2': 'Some structure but limited creativity',
                '3': 'Good structured approach with reasonable solutions',
                '4': 'Strong analytical thinking with creative solutions',
                '5': 'Exceptional problem-solving with innovative approaches'
              }
            }
          ]
        })
      }
    );
    const result = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    response = requests.patch(
        'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
        headers={
            'x-api-key': api_key,
            'Content-Type': 'application/json'
        },
        json={
            'interviewIds': ['int-uuid-1', 'int-uuid-2'],
            'mode': 'overwrite',
            'scoreCardTopics': [
                {
                    'topic': 'Technical Skills',
                    'weight': 40,
                    'description': 'Evaluate depth of technical knowledge',
                    'lookingFor': 'Strong understanding of core concepts and practical experience',
                    'scoreDescriptions': {
                        '1': 'No relevant technical knowledge',
                        '2': 'Basic understanding but limited experience',
                        '3': 'Solid knowledge with some practical experience',
                        '4': 'Strong expertise with extensive experience',
                        '5': 'Expert-level mastery with deep practical experience'
                    }
                },
                {
                    'topic': 'Communication',
                    'weight': 30,
                    'description': 'Evaluate clarity and effectiveness of communication',
                    'lookingFor': 'Clear, concise, and structured responses',
                    'scoreDescriptions': {
                        '1': 'Unable to communicate ideas clearly',
                        '2': 'Somewhat clear but disorganized',
                        '3': 'Clear and reasonably well-structured',
                        '4': 'Very clear, well-structured, and engaging',
                        '5': 'Exceptionally clear, persuasive, and articulate'
                    }
                },
                {
                    'topic': 'Problem Solving',
                    'weight': 30,
                    'description': 'Evaluate approach to solving problems',
                    'lookingFor': 'Structured thinking and creative solutions',
                    'scoreDescriptions': {
                        '1': 'No evidence of structured problem solving',
                        '2': 'Some structure but limited creativity',
                        '3': 'Good structured approach with reasonable solutions',
                        '4': 'Strong analytical thinking with creative solutions',
                        '5': 'Exceptional problem-solving with innovative approaches'
                    }
                }
            ]
        }
    )
    result = response.json()
    ```
  </Tab>
</Tabs>

### 9. Update Interview Settings (Overwrite)

Set language, web-only, and resume settings across interviews.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2", "int-uuid-3"],
    "mode": "overwrite",
    "language": "es",
    "webOnly": true,
    "resume": true
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 3,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 10. Set Notification Subscribers and Message Group (Overwrite)

Assign notification subscribers and a message group to multiple interviews.

<CodeGroup>
  ```json Request theme={null}
  {
    "interviewIds": ["int-uuid-1", "int-uuid-2"],
    "mode": "overwrite",
    "notificationSubscribers": ["user-uuid-1", "user-uuid-2", "user-uuid-3"],
    "messageGroupId": "msg-group-uuid"
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "success": true,
      "updatedCount": 2,
      "errors": [],
      "templateInterviewId": null
    }
  }
  ```
</CodeGroup>

### 11. Combined Merge (Questions + Keywords + Subscribers)

A realistic example that adds questions, keywords, and notification subscribers in a single merge operation.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X PATCH https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update \
      -H "x-api-key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{
        "interviewIds": ["int-uuid-1", "int-uuid-2", "int-uuid-3"],
        "mode": "merge",
        "audioQuestionAndMessageIds": ["q-uuid-new-1", "q-uuid-new-2"],
        "surveyQuestions": [
          { "id": "sq-uuid-new-1", "knockout": false },
          { "id": "sq-uuid-new-2", "knockout": true }
        ],
        "keywords": ["leadership", "management", "strategy"],
        "removedKeywords": ["entry-level"],
        "notificationSubscribers": ["user-uuid-hiring-mgr"]
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch(
      'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
      {
        method: 'PATCH',
        headers: {
          'x-api-key': apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          interviewIds: ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
          mode: 'merge',
          audioQuestionAndMessageIds: ['q-uuid-new-1', 'q-uuid-new-2'],
          surveyQuestions: [
            { id: 'sq-uuid-new-1', knockout: false },
            { id: 'sq-uuid-new-2', knockout: true }
          ],
          keywords: ['leadership', 'management', 'strategy'],
          removedKeywords: ['entry-level'],
          notificationSubscribers: ['user-uuid-hiring-mgr']
        })
      }
    );
    const result = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    response = requests.patch(
        'https://api.prod.qualifi.hr/qsi/gather/interviews/bulk-update',
        headers={
            'x-api-key': api_key,
            'Content-Type': 'application/json'
        },
        json={
            'interviewIds': ['int-uuid-1', 'int-uuid-2', 'int-uuid-3'],
            'mode': 'merge',
            'audioQuestionAndMessageIds': ['q-uuid-new-1', 'q-uuid-new-2'],
            'surveyQuestions': [
                {'id': 'sq-uuid-new-1', 'knockout': False},
                {'id': 'sq-uuid-new-2', 'knockout': True}
            ],
            'keywords': ['leadership', 'management', 'strategy'],
            'removedKeywords': ['entry-level'],
            'notificationSubscribers': ['user-uuid-hiring-mgr']
        }
    )
    result = response.json()
    ```
  </Tab>
</Tabs>

## Error Handling

| Status Code | Cause                                                          |
| ----------- | -------------------------------------------------------------- |
| `400`       | Missing `interviewIds` or empty array                          |
| `400`       | Missing or invalid `mode` (must be `"overwrite"` or `"merge"`) |
| `401`       | Invalid or missing API key                                     |
| `500`       | Internal server error                                          |

<Callout type="warning">
  Partial failures are possible — some interviews may update successfully while others fail. Always check the `errors` array in the response.
</Callout>

## Related Resources

<CardGroup cols={2}>
  <Card title="Interviews" icon="file-text" href="/api-reference/interviews">
    Create and manage individual interviews
  </Card>

  <Card title="Questions" icon="message-circle" href="/api-reference/questions">
    Create and manage interview questions
  </Card>

  <Card title="Best Practices" icon="check-circle" href="/guides/best-practices">
    API integration best practices
  </Card>
</CardGroup>
