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

# Candidates

> Create and manage candidate information

## Overview

Candidates represent individuals who will be invited to take interviews. You must create candidates before you can send interview invites.

## Create Candidate

Create a new candidate.

**Endpoint:** `POST /qsi/gather/candidates`

<ParamField name="firstName" type="string" required>
  Candidate's first name
</ParamField>

<ParamField name="lastName" type="string" required>
  Candidate's last name
</ParamField>

<ParamField name="email" type="string" required>
  Candidate's email address
</ParamField>

<ParamField name="phone" type="string" required>
  Candidate's phone number (E.164 format: +1234567890)
</ParamField>

<ParamField name="resumeUrl" type="string">
  Optional URL to candidate's resume
</ParamField>

<ParamField name="externalId" type="string">
  Optional external ID for your system integration
</ParamField>

<ParamField name="linkedInURL" type="string">
  Optional LinkedIn profile URL
</ParamField>

<ParamField name="source" type="string">
  Source of candidate (default: "api")
</ParamField>

<ParamField name="timezone" type="string">
  Candidate's timezone (e.g., "America/New\_York")
</ParamField>

<ParamField name="smsOptIn" type="boolean">
  Whether candidate opted in for SMS (default: false)
</ParamField>

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://api.prod.qualifi.hr/qsi/gather/candidates \
      -H "x-api-key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d "{
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com",
        "phone": "+1234567890"
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch('https://api.prod.qualifi.hr/qsi/gather/candidates', {
      method: 'POST',
      headers: {
        'x-api-key': apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        firstName: 'John',
        lastName: 'Doe',
        email: 'john.doe@example.com',
        phone: '+1234567890'
      })
    });
    const candidate = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    response = requests.post(
        'https://api.prod.qualifi.hr/qsi/gather/candidates',
        headers={
            'x-api-key': api_key,
            'Content-Type': 'application/json'
        },
        json={
            'firstName': 'John',
            'lastName': 'Doe',
            'email': 'john.doe@example.com',
            'phone': '+1234567890'
        }
    )
    candidate = response.json()
    ```
  </Tab>
</Tabs>

<CodeGroup>
  ```json Request theme={null}
  {
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "phone": "+1234567890",
    "externalId": "candidate-123",
    "timezone": "America/New_York",
    "smsOptIn": true
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "id": "uuid",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phone": "+1234567890",
      "createdAt": "2024-01-01T00:00:00Z"
    },
    "meta": {
      "requestId": "uuid",
      "timestamp": "2024-01-01T00:00:00Z"
    }
  }
  ```
</CodeGroup>

## Get Candidate

Retrieve candidate details.

**Endpoint:** `GET /qsi/gather/candidates/{candidateId}`

<ParamField path="candidateId" type="string" required>
  UUID of the candidate
</ParamField>

<CodeGroup>
  ```json Response theme={null}
  {
    "data": {
      "id": "uuid",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phone": "+1234567890",
      "resumeUrl": "https://...",
      "externalId": "candidate-123",
      "linkedInURL": "https://linkedin.com/in/johndoe",
      "source": "api",
      "timezone": "America/New_York",
      "smsOptIn": true,
      "createdAt": "2024-01-01T00:00:00Z",
      "updatedAt": "2024-01-01T00:00:00Z"
    },
    "meta": {
      "requestId": "uuid",
      "timestamp": "2024-01-01T00:00:00Z"
    }
  }
  ```
</CodeGroup>

## List Candidates

List all candidates with pagination and filtering.

**Endpoint:** `GET /qsi/gather/candidates`

<ParamField query="page" type="number">
  Page number (default: 1)
</ParamField>

<ParamField query="pageSize" type="number">
  Items per page (default: 10, max: 100)
</ParamField>

<ParamField query="archived" type="boolean">
  Include archived candidates (default: false)
</ParamField>

<ParamField query="search" type="string">
  Search by name or email
</ParamField>

<ParamField query="externalId" type="string">
  Filter by external ID
</ParamField>

<CodeGroup>
  ```json Response theme={null}
  {
    "data": {
      "candidates": [
        {
          "id": "uuid",
          "firstName": "John",
          "lastName": "Doe",
          "email": "john.doe@example.com",
          "phone": "+1234567890",
          "resumeUrl": "https://example.com/resume.pdf",
          "externalId": "ext-123",
          "timezone": "America/New_York",
          "smsOptIn": true,
          "organizationId": "org-uuid",
          "teamId": "team-uuid",
          "createdById": "user-uuid",
          "createdAt": "2024-01-01T00:00:00Z",
          "updatedAt": "2024-01-01T00:00:00Z"
        }
      ],
      "pagination": {
        "total": 42,
        "page": 1,
        "pages": 5,
        "pageSize": 10
      }
    },
    "meta": {
      "requestId": "uuid",
      "timestamp": "2024-01-01T00:00:00Z"
    }
  }
  ```
</CodeGroup>

## Update Candidate

Update candidate information.

**Endpoint:** `PATCH /qsi/gather/candidates/{candidateId}`

<ParamField path="candidateId" type="string" required>
  UUID of the candidate to update
</ParamField>

<ParamField name="firstName" type="string">
  Updated first name
</ParamField>

<ParamField name="lastName" type="string">
  Updated last name
</ParamField>

<ParamField name="email" type="string">
  Updated email
</ParamField>

<ParamField name="phone" type="string">
  Updated phone number
</ParamField>

<ParamField name="resumeUrl" type="string">
  Updated resume URL
</ParamField>

<ParamField name="externalId" type="string">
  Updated external ID
</ParamField>

<CodeGroup>
  ```json Request theme={null}
  {
    "firstName": "Jane",
    "email": "jane.doe@example.com"
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "id": "uuid",
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane.doe@example.com",
      "updatedAt": "2024-01-01T00:00:00Z"
    },
    "meta": {
      "requestId": "uuid",
      "timestamp": "2024-01-01T00:00:00Z"
    }
  }
  ```
</CodeGroup>

## Delete Candidate

Archive a candidate.

**Endpoint:** `DELETE /qsi/gather/candidates/{candidateId}`

<ParamField path="candidateId" type="string" required>
  UUID of the candidate to archive
</ParamField>

<CodeGroup>
  ```json Response theme={null}
  {
    "data": {
      "id": "uuid",
      "archivedAt": "2024-01-01T00:00:00Z"
    },
    "meta": {
      "requestId": "uuid",
      "timestamp": "2024-01-01T00:00:00Z"
    }
  }
  ```
</CodeGroup>

## Phone Number Format

Phone numbers must be in E.164 format:

* ✅ `+1234567890`
* ❌ `123-456-7890`
* ❌ `(123) 456-7890`

<Callout type="warning">
  Ensure phone numbers include country code and are in E.164 format for proper
  delivery of SMS and phone call invites.
</Callout>

## External IDs

Use `externalId` to maintain references to candidates in your own system:

* Helps track candidates across systems
* Useful for syncing data between Qualifi and your ATS
* Can be used for filtering and searching

## Related Resources

<CardGroup cols={2}>
  <Card title="Candidate Interviews" icon="file-text" href="/api-reference/candidate-interviews">
    Send interview invites to candidates
  </Card>

  <Card title="Sending Invites" icon="mail" href="/guides/sending-invites">
    Learn how to send interview invites
  </Card>
</CardGroup>
