Updated June 15, 2026
GET
/api/v1/candidates
curl -X GET \
"https://app.recruitsome.com/api/v1/candidates" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const response = await fetch('https://app.recruitsome.com/api/v1/candidates', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Accept': 'application/json',
},
});
const data = await response.json();
console.log(data);
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_KEY')
->acceptJson()
->get('https://app.recruitsome.com/api/v1/candidates');
$data = $response->json();
Retrieve a paginated list of candidates associated with a specific user. Candidates are scoped to the user's repository — only candidates that have been associated with the given user are returned.
Authentication
Requires an API key with the candidates:read scope (included in the Chrome Plugin preset). Calls with a key that lacks the scope return a 403 with error code INSUFFICIENT_SCOPE.
Endpoint
GET /api/v1/candidatesQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
user_id | integer | - | Required. The tenant user ID whose candidate repository to query |
email | string | - | Filter by exact email address match |
search | string | - | Search in first name, last name, and email (partial match) |
status | string | - | Filter by candidate status (see Status Values below) |
sort | string | created_at | Sort field: created_at, first_name, last_name, email |
sort_direction | string | desc | Sort direction: asc or desc |
page | integer | 1 | Page number for pagination |
per_page | integer | 20 | Items per page (max: 100) |
Status Values
| Value | Description |
|---|---|
potential | New candidate, not yet contacted |
waiting_for_intake | Contacted and interested, awaiting intake |
intake_scheduled | Intake meeting has been planned |
active_mediation | Actively being placed in procedures |
latent_mediation | Available but not actively being placed |
upcoming_employee | Accepted an offer, starting soon |
employee | Currently employed |
ex_employee | Former employee |
do_not_contact | Should not be contacted |
Response Fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique candidate ID |
slug | string | URL-friendly identifier |
first_name | string | First/given name |
middle_name | string|null | Middle name or prefix |
last_name | string | Last/family name |
full_name | string | Computed full name |
email | string | Email address |
mobile_phone | string|null | Mobile phone number, formatted for display |
fixed_phone | string|null | Landline phone number in raw E.164 format (e.g., +31201234567) |
status | object | Current candidate status |
locality | string|null | City/town |
country_code | string|null | ISO 3166-1 alpha-2 country code |
linkedin_url | string|null | LinkedIn profile URL |
profile_completeness | integer|null | Profile completeness percentage (0-100) |
avatar | object | Avatar image URLs |
created_at | string | ISO 8601 creation date |
updated_at | string | ISO 8601 last update date |
Object Structures
Status Object
{
"value": "potential",
"label": "Potential Candidate"
}Avatar Object
{
"small": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-thumb.jpg",
"medium": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-medium.jpg",
"large": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-large.jpg"
}Avatar URLs may be null if the candidate has no profile photo.
Pagination
The response includes standard pagination metadata:
{
"data": [...],
"links": {
"first": "https://app.recruitsome.com/api/v1/candidates?page=1",
"last": "https://app.recruitsome.com/api/v1/candidates?page=3",
"prev": null,
"next": "https://app.recruitsome.com/api/v1/candidates?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 3,
"path": "https://app.recruitsome.com/api/v1/candidates",
"per_page": 20,
"to": 20,
"total": 52
}
}Example Request
Basic Request
curl -X GET "https://app.recruitsome.com/api/v1/candidates?user_id=1" \
-H "Authorization: Bearer YOUR_API_KEY"const response = await fetch(
'https://app.recruitsome.com/api/v1/candidates?user_id=1',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
const data = await response.json();
console.log(data);import requests
response = requests.get(
'https://app.recruitsome.com/api/v1/candidates',
params={'user_id': 1},
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
print(data)Find Candidate by Email
curl -X GET "https://app.recruitsome.com/api/v1/candidates?user_id=1&[email protected]" \
-H "Authorization: Bearer YOUR_API_KEY"const response = await fetch(
'https://app.recruitsome.com/api/v1/candidates?user_id=1&[email protected]',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);response = requests.get(
'https://app.recruitsome.com/api/v1/candidates',
params={
'user_id': 1,
'email': '[email protected]'
},
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)With Filters
curl -X GET "https://app.recruitsome.com/api/v1/candidates?user_id=1&search=developer&status=active_mediation&sort=last_name&sort_direction=asc" \
-H "Authorization: Bearer YOUR_API_KEY"Example Response
{
"data": [
{
"id": 42,
"slug": "john-doe-amsterdam",
"first_name": "John",
"middle_name": null,
"last_name": "Doe",
"full_name": "John Doe",
"email": "[email protected]",
"mobile_phone": "+31 6 12345678",
"fixed_phone": null,
"status": {
"value": "potential",
"label": "Potential Candidate"
},
"locality": "Amsterdam",
"country_code": "NL",
"linkedin_url": "https://linkedin.com/in/johndoe",
"profile_completeness": 75,
"avatar": {
"small": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-thumb.jpg",
"medium": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-medium.jpg",
"large": "https://app.recruitsome.com/media/candidates/42/conversions/avatar-large.jpg"
},
"created_at": "2024-01-15T09:00:00+00:00",
"updated_at": "2024-01-20T14:30:00+00:00"
}
],
"links": {
"first": "https://app.recruitsome.com/api/v1/candidates?page=1",
"last": "https://app.recruitsome.com/api/v1/candidates?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://app.recruitsome.com/api/v1/candidates",
"per_page": 20,
"to": 1,
"total": 1
}
}Errors
| Status | When | Body |
|---|---|---|
422 | user_id is missing or doesn't reference an existing user | {"message": "The given data was invalid.", "errors": {"user_id": ["The user id field is required."]}} |
422 | email filter isn't a valid email address, or search exceeds 255 characters | Same shape, with the offending field in errors |
401 | Missing or invalid API key | {"message": "Unauthenticated."} |
403 | API key lacks the candidates:read scope | {"message": "This API key does not have the required permission: candidates:read", "error": "INSUFFICIENT_SCOPE", "required_scope": "candidates:read"} |
Notes
- The
user_idparameter is required — candidates are scoped to a specific user's repository - Only candidates that have been associated with the given user are returned
- Soft-deleted candidates are automatically excluded
- The
emailfilter performs an exact match; usesearchfor partial matching - The
searchparameter performs a case-insensitive partial match across first name, last name, and email mobile_phoneis returned formatted for display;fixed_phoneis returned as a raw E.164 string- Avatar URLs may be
nullif the candidate has no profile photo uploaded