> This page is for API, version 2026-01-01 (Stable) (default).
> For other versions, use one of these documentation indexes:
> - 2026-01-01 (Stable) (default): https://docs.deel.wtf/api/stable/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.deel.wtf/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.deel.wtf/_mcp/server.

# List candidates

GET https://api.letsdeel.com/rest/talent/candidates

Returns a cursor-paginated list of the candidates submitted to the Deel Talent job requests of the organization, with their pipeline status and the talent partner that sourced them, newest first. Filter by status, job request or talent partner. Pass the cursor from each response to retrieve the next page, and keep requesting until `data` is empty.

 **Token scopes**: `talents:read`

 **Beta**: this version requires the `X-Beta: true` request header and its contract may change before it is promoted to stable. It is scheduled to become stable on 2027-01-23.

Reference: https://docs.deel.wtf/api/reference/endpoints/talent/list-candidates-v-2026-10-23

## Authentication

- `Authorization` header (bearer token, required) — ## Authentication The Deel API uses bearer tokens to authenticate requests. All API calls must be made over HTTPS — calls over plain HTTP or without authentication will fail. ```curl curl -X GET 'https://api.deel.training/rest/v2/contracts' \ -H 'Authorization: Bearer YOUR-TOKEN-HERE' ``` [Learn more about authentication](/api/authentication)
- `Authorization` header (bearer token, required) — Standard OAuth2 security scheme based on https://swagger.io/docs/specification/authentication/

## Servers

- `https://api.letsdeel.com/rest` (Production, default)
- `https://api-staging.letsdeel.com/rest` (Demo)

## Request

### Query parameters

- `status` (list of enum, optional, default: []) — Filter by candidate status.
  - Allowed values: `CANCELLED_BY_HIRER`, `CANCELLED_BY_VENDOR`, `CONTRACT_CREATED`, `INITIAL_SCREENING_REJECTED`, `INTERVIEW_REJECTED`, `OFFER_ACCEPTED`, `OFFER_REJECTED`, `OFFER_SENT`, `PENDING_INITIAL_SCREENING`, `PENDING_INTERVIEW`, `WAITING_FOR_OFFER`
- `requisition_ids` (list of string, optional, default: []) — Filter by job request identifiers.
- `vendor_ids` (list of string, optional, default: []) — Filter by talent partner identifiers. The reserved value `external_provider` matches candidates sourced from an external provider rather than a Deel talent partner.
- `cursor` (string, optional, default: ) — Opaque cursor returned by the previous page. Omit to retrieve the first page.
- `limit` (integer, optional, default: 10) — Maximum number of records to return.

### Headers

- `X-Beta` (enum, required, default: true) — Opts in to the beta version of this endpoint. Must be `true`.
  - Allowed values: `true`

## Response

### 200

Successful operation.

- `data` (list of TalentCandidatesGetResponsesContentApplicationJsonSchemaDataItems, required) — The candidates on the requested page.
- `page` (TalentCandidatesGetResponsesContentApplicationJsonSchemaPage, required) — Pagination details.

## Errors

### 400 Bad Request Error

Invalid filters, unknown query parameters, a malformed cursor, or a job request or talent partner identifier that does not exist.

- `ListCandidates-v2026-10-23RequestBadRequestError`
  - ListCandidatesV20261023RequestBadRequestError0
  - ListCandidatesV20261023RequestBadRequestError1

### 401 Unauthorized Error

Token missing or invalid.

- `code` (string, required) — Machine-readable error code.
- `error` (string, optional) — Human-readable explanation, when it differs from `code`.

### 403 Forbidden Error

The caller lacks permission to view the Deel Talent data of the organization.

- `code` (string, required) — Machine-readable error code.
- `error` (string, optional) — Human-readable explanation, when it differs from `code`.

### 404 Not Found Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 429 Too Many Requests Error

Rate limit exceeded — retry honouring `Retry-After`.

- `any`

### 500 Internal Server Error

Unexpected error.

- `code` (string, required) — Machine-readable error code.
- `error` (string, optional) — Human-readable explanation, when it differs from `code`.

## Types

### TalentCandidatesGetResponsesContentApplicationJsonSchemaDataItems

- `id` (string, required) — Unique identifier of the candidate.
- `email` (string, required, nullable) — Candidate email. `null` when the talent partner did not share it.
- `status` (enum, required) — Current pipeline status of the candidate.
  - Allowed values: `CANCELLED_BY_HIRER`, `CANCELLED_BY_VENDOR`, `CONTRACT_CREATED`, `INITIAL_SCREENING_REJECTED`, `INTERVIEW_REJECTED`, `OFFER_ACCEPTED`, `OFFER_REJECTED`, `OFFER_SENT`, `PENDING_INITIAL_SCREENING`, `PENDING_INTERVIEW`, `WAITING_FOR_OFFER`
- `vendor` (TalentCandidatesGetResponsesContentApplicationJsonSchemaDataItemsVendor, required, nullable) — Talent partner that submitted the candidate. `null` when sourced from an external provider.
- `full_name` (string, required) — Candidate full name.
- `last_name` (string, required) — Candidate last name.
- `created_at` (string, required) — When the candidate was submitted.
- `first_name` (string, required) — Candidate first name.
- `requisition_id` (string, required) — Identifier of the job request the candidate was submitted to.
- `creation_source` (enum, required) — How the candidate was sourced: by a talent partner or by an external provider.
  - Allowed values: `HACKAJOB`, `VMS_VENDOR`
- `status_updated_at` (string, required) — When the candidate status last changed.

### TalentCandidatesGetResponsesContentApplicationJsonSchemaPage

Pagination details.

- `cursor` (string, required) — Cursor to pass to the next request. Still set on the last page; the end of the list is reached when a request returns an empty `data` and an empty cursor.
- `total_rows` (integer, required, nullable) — Total number of candidates matching the filters. Returned on the first page only, `null` afterwards.

### ListCandidatesV20261023RequestBadRequestError0

- `code` (string, required) — Machine-readable error code.
- `errors` (list of TalentCandidatesGetResponsesContentApplicationJsonSchemaOneOf0ErrorsItems, required) — The query parameters that failed validation.

### ListCandidatesV20261023RequestBadRequestError1

- `code` (string, required) — Machine-readable error code.
- `error` (string, optional) — Human-readable explanation, when it differs from `code`.

### ApiErrorRequest

- `method` (string, optional) — The HTTP method of the failed request
- `url` (string, optional) — The relative URL of the failed request
- `status` (double, optional) — The status code of the response
- `api_req_id` (string, optional) — The request ID of the failed request
- `docs` (string, optional) — A link to the official documentation for the requested endpoint resource
- `source` (string, optional) — The source handler which produced the returned error
- `code` (double, optional) — The code of the source handler which produced the returned error

### ApiError

- `message` (string, optional) — A description of the returned error
- `path` (string, optional) — The JSON path where input validation failed

### TalentCandidatesGetResponsesContentApplicationJsonSchemaDataItemsVendor

Talent partner that submitted the candidate. `null` when sourced from an external provider.

- `id` (string, required) — Unique identifier of the talent partner.
- `name` (string, required) — Talent partner name.

### TalentCandidatesGetResponsesContentApplicationJsonSchemaOneOf0ErrorsItems

- `messages` (list of string, required) — Why it is invalid.
- `property` (string, required) — Name of the invalid parameter.

## Examples

**Response**

```json
{
  "data": [
    {
      "id": "5f2b8c91-77d4-4a3e-8b6c-0e1d9a4f2c38",
      "email": "grace.hopper@example.com",
      "status": "PENDING_INTERVIEW",
      "vendor": {
        "id": "8a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44",
        "name": "Acme Staffing"
      },
      "full_name": "Grace Hopper",
      "last_name": "Hopper",
      "created_at": "2026-07-01T10:15:00.000Z",
      "first_name": "Grace",
      "requisition_id": "3cfbb359-6084-46c0-9d3f-1ed1a1007a7a",
      "creation_source": "VMS_VENDOR",
      "status_updated_at": "2026-08-20T16:45:00.000Z"
    }
  ],
  "page": {
    "cursor": "eyJhZnRlcklkIjoxMjM0fQ",
    "total_rows": 42
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/talent/candidates"

querystring = {"cursor":"eyJhZnRlcklkIjoxMjM0fQ","limit":"10","requisition_ids":"[\"3cfbb359-6084-46c0-9d3f-1ed1a1007a7a\"]","status":"[\"PENDING_INTERVIEW\"]","vendor_ids":"[\"8a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44\",\"external_provider\"]"}

headers = {
    "X-Beta": "true",
    "Authorization": "Bearer <token>"
}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D';
const options = {method: 'GET', headers: {'X-Beta': 'true', Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-Beta", "true")
	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'X-Beta' => 'true',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D");
var request = new RestRequest(Method.GET);
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-Beta": "true",
  "Authorization": "Bearer <token>"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/talent/candidates?cursor=eyJhZnRlcklkIjoxMjM0fQ&limit=10&requisition_ids=%5B%223cfbb359-6084-46c0-9d3f-1ed1a1007a7a%22%5D&status=%5B%22PENDING_INTERVIEW%22%5D&vendor_ids=%5B%228a1f0c74-2b16-4f8e-9a0d-5c3e7b219d44%22%2C%22external_provider%22%5D")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```