# listCandidates

Source: /openapi/thomas-federated.openapi.json

## Operation

| Method | URL |
|---|---|
| GET | https://api.thomas.co/v1/candidates |

| Field | Value |
|---|---|
| operationId | listCandidates |
| method | GET |
| server | https://api.thomas.co |
| path | /v1/candidates |
| tags | `Recruitment` |
| summary | List candidates |
| badges | `{"name":"Admin"}`, `{"name":"Owner"}` |
| scopes | `users:r` |

## Description

A page of the candidates in the tenant, filtered, searched and sorted by the query. A human caller sees the candidates their confidential-visibility allows. A Partner API client requires a tenant context and `users:r`, and receives the same rows the tenant Owner receives, confidential candidates included. On behalf of a named person (`Thomas-On-Behalf-Of`), a Partner receives exactly the rows that person receives signed in: candidates in circles the person is not in are omitted.

## Request Parameters

| Name | In | Required | Schema | Description |
|---|---|---|---|---|
| page | query | false | integer |  |
| pageSize | query | false | integer |  |
| search | query | false | string |  |
| connectionPower | query | true | array |  |
| status | query | false | string | Candidate Aggregate status (FR-2): a single rolled-up status derived across in-scope per-assessment statuses. This same value set is also the per-assessment status vocabulary. |
| segment | query | false | string |  |
| sortBy | query | false | string |  |
| sortOrder | query | false | string |  |
| Thomas-On-Behalf-Of | header | false | string | Optional for a Partner API client on this operation. Send it to act on behalf of one named person: thomas:<companyIndividualId> or partner:<partnerReference>. The call is then authorised as that person, within that person's access circles and the scopes your Grant holds. Omit it to call as your API client. A signed-in person never sends it. |
| Thomas-Tenant-Id | header | true | string:uuid | Required for API clients: the Tenant this call acts in. Send exactly one. Signed-in users don't send it — their Tenant comes from their session. The header only selects the Tenant; your Grant for it decides access, and is checked on every call. |

## Request Body

None.

## Responses

| Status | Description | Schema refs |
|---|---|---|
| 200 | A page of candidates | #/components/schemas/CandidateListResponseDto |
| 400 | Invalid query parameters. A Partner may also send a malformed tenant or person selector. Also returned when the Thomas-On-Behalf-Of header is repeated or malformed. | #/components/schemas/ApiErrorResponseDto |
| 401 | Invalid or missing authentication token (AUTH_TOKEN_INVALID) | #/components/schemas/ApiErrorResponseDto |
| 403 | Refused when the caller has insufficient role (owner or admin required), envelope `AUTH_INSUFFICIENT_ROLE`, or when the tenant’s effective plan tier does not include the Candidates capability, envelope `INSUFFICIENT_TIER` — a Partner API client is held to the tenant’s plan too. An API client is refused before any tenant data is read or changed when its tenant context, Grant or scope does not authorise the operation (AUTH_TENANT_NOT_GRANTED), when its service membership is absent (AUTH_SERVICE_MEMBERSHIP_MISSING), or when the operation is not published to its principal kind (PRINCIPAL_TYPE_NOT_ALLOWED). An API client holds no organisation role, so AUTH_INSUFFICIENT_ROLE never applies to it. | #/components/schemas/ApiErrorResponseDto |
| 404 | The named acting person is unavailable. | #/components/schemas/ApiErrorResponseDto |
| 429 | Rate limit exceeded. | #/components/schemas/ApiErrorResponseDto |

### Response 429 headers

| Name | Description | Schema |
|---|---|---|
| Retry-After | Seconds until the rate-limit block expires before retrying. | {"type":"integer","minimum":0} |
| RateLimit-Limit | Configured request limit for the active rate-limit window. | {"type":"integer"} |
| RateLimit-Remaining | Requests remaining in the active rate-limit window; zero when blocked. | {"type":"integer"} |
| RateLimit-Reset | Seconds until the rate-limit block expires. | {"type":"integer","minimum":0} |

## Artifact Examples

### Response 400 example — HTTP_BAD_REQUEST

```json
{
  "statusCode": 400,
  "message": "Validation failed",
  "error": "HTTP_BAD_REQUEST",
  "details": {
    "validationIssues": [
      {
        "path": "$",
        "rule": "invalid_type"
      }
    ]
  }
}
```

### Response 400 example — AUTH_TENANT_CONTEXT_INVALID (Malformed person selector)

```json
{
  "statusCode": 400,
  "message": "Exactly one valid Thomas-On-Behalf-Of header is required",
  "error": "AUTH_TENANT_CONTEXT_INVALID"
}
```

### Response 400 example — AUTH_TENANT_CONTEXT_INVALID (Missing or malformed tenant selector)

```json
{
  "statusCode": 400,
  "message": "Exactly one valid Thomas-Tenant-Id header is required",
  "error": "AUTH_TENANT_CONTEXT_INVALID"
}
```

### Response 401 example

```json
{
  "statusCode": 401,
  "message": "Invalid or missing authentication token",
  "error": "AUTH_TOKEN_INVALID"
}
```

### Response 403 example — AUTH_INSUFFICIENT_ROLE

```json
{
  "statusCode": 403,
  "message": "Insufficient role privileges",
  "error": "AUTH_INSUFFICIENT_ROLE"
}
```

### Response 403 example — AUTH_TENANT_NOT_GRANTED (Tenant not granted)

```json
{
  "statusCode": 403,
  "message": "API client is not granted access to this tenant",
  "error": "AUTH_TENANT_NOT_GRANTED"
}
```

### Response 403 example — PRINCIPAL_TYPE_NOT_ALLOWED (Principal kind not allowed)

```json
{
  "statusCode": 403,
  "message": "On-behalf access is not permitted for this operation",
  "error": "PRINCIPAL_TYPE_NOT_ALLOWED"
}
```

### Response 403 example — AUTH_TENANT_NOT_GRANTED (No Grant or scope for this tenant)

```json
{
  "statusCode": 403,
  "message": "API client is not granted access to this tenant",
  "error": "AUTH_TENANT_NOT_GRANTED"
}
```

### Response 403 example — AUTH_SERVICE_MEMBERSHIP_MISSING

```json
{
  "statusCode": 403,
  "message": "API client has no active service membership in this tenant",
  "error": "AUTH_SERVICE_MEMBERSHIP_MISSING"
}
```

### Response 403 example — PRINCIPAL_TYPE_NOT_ALLOWED (This operation is not published to the calling principal kind)

```json
{
  "statusCode": 403,
  "message": "API client is not permitted to call this operation",
  "error": "PRINCIPAL_TYPE_NOT_ALLOWED"
}
```

### Response 404 example — AUTH_ON_BEHALF_PERSON_NOT_AVAILABLE

```json
{
  "statusCode": 404,
  "message": "The named person is not available for this operation",
  "error": "AUTH_ON_BEHALF_PERSON_NOT_AVAILABLE"
}
```

### Response 429 example

```json
{
  "statusCode": 429,
  "message": "ThrottlerException: Too Many Requests",
  "error": "HTTP_TOO_MANY_REQUESTS"
}
```
