Updated July 1, 2026
/api/v1/vacancies
curl -X GET \
"https://app.recruitsome.com/api/v1/vacancies" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const response = await fetch('https://app.recruitsome.com/api/v1/vacancies', {
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/vacancies');
$data = $response->json();
Retrieve a paginated list of active vacancy publications — the feed your career website uses to render its job overview page, with filtering, sorting, and optional facet counts for building filter UIs.
Authentication
Requires an API key with the vacancies:read scope (included in the Career website preset). A key without this scope receives a 403 response.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number for pagination |
per_page | integer | 20 | Items per page (max: 100) |
search | string | - | Search in title and summary (case-insensitive) |
language | string | - | Filter by language code (exactly 2 characters, e.g. nl). Also sets the locale for translated fields. |
location_id | integer | - | Filter by a single location ID. Array notation is not accepted here (returns a 422) — use the facets endpoint or repeat requests per location. |
department_id | integer | - | Filter by a single department ID. Array notation is not accepted here (returns a 422). |
company_location_id[] | array | - | Filter by company location ID(s) (work site, for agency tenants). The only ID filter on this endpoint that accepts multiple values: company_location_id[]=1&company_location_id[]=2 |
experience_levels[] | array | - | Filter by experience level IDs |
education_levels[] | array | - | Filter by education level IDs |
job_types[] | array | - | Filter by job type IDs |
tags[] | array | - | Filter by tag IDs (main tags cascade to include sub-tags) |
sort | string | published_at | Sort field: published_at, title, created_at |
sort_direction | string | desc | Sort direction: asc or desc |
include | string | - | Include additional data: facets |
include_media | boolean | false | Include header_image and images |
include_compensation | boolean | false | Include basic compensation data |
include_company_name | boolean | false | Include company name in the company_location object (opt-in for privacy) |
Response fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique vacancy publication ID |
slug | string | URL-friendly identifier |
title | string | Vacancy title |
summary | string | Brief description (HTML) |
language | string | Language code (ISO 639-1) |
published_at | string | ISO 8601 publication date |
ends_at | string|null | ISO 8601 expiration date |
views_count | integer | Number of times viewed |
location | object|null | Location details (office/branch location) |
company_location | object|null | Company location details (actual work site, for agency tenants) |
department | object|null | Department details |
hiring_manager | object|null | Hiring manager details |
education_levels | array | Required education levels (may be empty) |
job_types | array | Employment types (may be empty) |
experience_levels | array | Experience/seniority levels (e.g., Junior, Medior, Senior, Lead; may be empty) |
work_arrangement | object | Work model: on-site, hybrid, or remote. Key is absent when the vacancy has no work arrangement set. |
tags | array | Job category tags (main and sub-categories; may be empty) |
classification | object|null | The tenant's classification label (name, stable key, color). Key is absent unless the tenant has enabled vacancy classification; null when enabled but no label is assigned. |
application_url | string | URL to apply for this position |
metadata | object | Additional vacancy metadata |
header_image | object|null | Header image URLs. Key is absent unless include_media=true. |
images | object | Map of all configured image crops. Key is absent unless include_media=true. |
compensation | object|null | Basic compensation data. Key is absent unless include_compensation=true. |
Null vs absent
The core relationship fields (location, company_location, department, hiring_manager) are always present in the response — they are null when the vacancy has no value for them. The opt-in fields (header_image, images, compensation) and work_arrangement behave differently: when their condition isn't met, the key is omitted entirely, not set to null. Check for key existence before reading them.
Object structures
Location object
{
"id": 3,
"name": "Amsterdam Office",
"city": "Amsterdam",
"country_code": "NL",
"country_name": "Netherlands"
}Company location object
The work site location for agency vacancies. Returns null for non-agency tenants or when no company location is assigned.
{
"id": 17,
"name": "Shell Pernis Refinery",
"city": "Rotterdam",
"country_code": "NL",
"country_name": "Netherlands",
"company_name": "Shell Nederland B.V."
}The company_name key is only present when include_company_name=true is passed. This is opt-in to prevent accidentally exposing which client company an agency is recruiting for.
Department object
{
"id": 5,
"name": "Maintenance & Engineering"
}Hiring manager object
The avatar field is a single URL string pointing to the medium-size avatar (256x256), or null when no avatar has been uploaded — it is not an object with multiple sizes.
{
"given_name": "Sanne",
"family_name": "de Vries",
"full_name": "Sanne de Vries",
"job_title": "Recruitment Manager",
"email": "[email protected]",
"avatar": "https://app.recruitsome.com/media/avatars/12/medium.jpg"
}Education level object
{
"id": 1,
"name": "Bachelor"
}Job type object
{
"id": 1,
"name": "Full-time"
}Experience level object
{
"id": 3,
"name": "Senior"
}Possible values: Junior, Medior, Senior, Lead. Returns an empty array when no experience level is assigned.
Work arrangement object
{
"value": "hybrid",
"label": "Hybride"
}The value field contains the canonical identifier: on_site, remote, or hybrid. The label is the localized display name (respects the language parameter). Remember: this key is omitted entirely when the vacancy has no work arrangement set.
Tag object
{
"id": 5,
"name": "Software Engineer",
"type": "sub",
"parent_id": 1
}The type field indicates whether the tag is a main category or a sub category. Main tags have parent_id: null.
Classification object
{
"name": "Priority A",
"key": "priority_a",
"color": "rose"
}key is a stable identifier derived from the label's name; it survives renames, so match on key rather than name. color is one of rose, amber, emerald, sky, violet, gray, or null.
Metadata object
{
"status": "active"
}Compensation object (when include_compensation=true)
Basic compensation summary for the list view:
{
"salary_range": {
"min": 3500,
"max": 5000,
"currency": "EUR",
"period": "monthly"
},
"contract_hours": 40
}salary_range is null when the vacancy has no salary set. For full compensation details (including the holidays breakdown), use the detail endpoint with include_compensation=true.
Header image object (legacy, when include_media=true)
{
"small": "https://app.recruitsome.com/media/vacancies/412/header-small.jpg",
"medium": "https://app.recruitsome.com/media/vacancies/412/header-medium.jpg",
"large": "https://app.recruitsome.com/media/vacancies/412/header-large.jpg",
"xlarge": "https://app.recruitsome.com/media/vacancies/412/header-xlarge.jpg",
"original": "https://app.recruitsome.com/media/vacancies/412/header.jpg"
}Images object (when include_media=true)
Map of all configured image crops. The default key corresponds to the legacy header_image. Each entry also carries internal variant_settings and photo_library_item_id metadata you can ignore.
{
"default": {
"url": "https://app.recruitsome.com/media/vacancies/412/header-large.jpg",
"width": 1200,
"height": 675,
"mime_type": "image/jpeg"
},
"narrow_casting": {
"url": "https://app.recruitsome.com/media/vacancies/412/narrow-casting.jpg",
"width": 1080,
"height": 1920,
"mime_type": "image/jpeg"
}
}Example
curl -X GET "https://app.recruitsome.com/api/v1/vacancies?search=engineer&location_id=3&include_compensation=true" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"const params = new URLSearchParams({
search: 'engineer',
location_id: '3',
include_compensation: 'true'
});
const response = await fetch(`https://app.recruitsome.com/api/v1/vacancies?${params}`, {
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Accept': 'application/json'
}
});
const vacancies = await response.json();Response 200
{
"data": [
{
"id": 412,
"slug": "maintenance-engineer",
"title": "Maintenance Engineer",
"summary": "<p>Keep our Rotterdam production lines running as part of a five-person technical service team.</p>",
"language": "en",
"published_at": "2026-05-12T09:00:00+00:00",
"ends_at": "2026-07-12T23:59:59+00:00",
"views_count": 42,
"location": {
"id": 3,
"name": "Amsterdam Office",
"city": "Amsterdam",
"country_code": "NL",
"country_name": "Netherlands"
},
"company_location": null,
"department": {
"id": 5,
"name": "Maintenance & Engineering"
},
"hiring_manager": {
"given_name": "Sanne",
"family_name": "de Vries",
"full_name": "Sanne de Vries",
"job_title": "Recruitment Manager",
"email": "[email protected]",
"avatar": null
},
"education_levels": [
{
"id": 1,
"name": "Bachelor"
}
],
"job_types": [
{
"id": 1,
"name": "Full-time"
}
],
"experience_levels": [
{
"id": 3,
"name": "Senior"
}
],
"work_arrangement": {
"value": "hybrid",
"label": "Hybrid"
},
"tags": [
{
"id": 1,
"name": "Engineering",
"type": "main",
"parent_id": null
},
{
"id": 5,
"name": "Maintenance Engineer",
"type": "sub",
"parent_id": 1
}
],
"classification": {
"name": "Priority A",
"key": "priority_a",
"color": "rose"
},
"compensation": {
"salary_range": {
"min": 3500,
"max": 5000,
"currency": "EUR",
"period": "monthly"
},
"contract_hours": 40
},
"application_url": "https://www.yourcompany.com/vacatures/maintenance-engineer",
"metadata": {
"status": "active"
}
}
],
"links": {
"first": "https://app.recruitsome.com/api/v1/vacancies?page=1",
"last": "https://app.recruitsome.com/api/v1/vacancies?page=5",
"prev": null,
"next": "https://app.recruitsome.com/api/v1/vacancies?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"path": "https://app.recruitsome.com/api/v1/vacancies",
"per_page": 20,
"to": 20,
"total": 94
}
}Facets
When include=facets is specified, a facets object is added to meta (the key is absent otherwise) with aggregated counts per filter option. The structure is identical to the response of the standalone facets endpoint:
{
"meta": {
"facets": {
"locations": [
{
"id": 3,
"name": "Amsterdam Office",
"city": "Amsterdam",
"country_code": "NL",
"country_name": "Netherlands",
"count": 15,
"selected": false
}
],
"company_locations": [
{
"id": 17,
"name": "Shell Pernis Refinery",
"city": "Rotterdam",
"country_code": "NL",
"country_name": "Netherlands",
"count": 5,
"selected": false
}
],
"departments": [
{
"id": 5,
"name": "Maintenance & Engineering",
"count": 23,
"selected": false
}
],
"experience_levels": [
{
"id": 3,
"name": "Senior",
"count": 12,
"selected": false
}
],
"education_levels": [
{
"id": 8,
"name": "Bachelor",
"count": 28,
"selected": false
}
],
"job_types": [
{
"id": 1,
"name": "Full-time",
"count": 45,
"selected": false
}
],
"tags": [
{
"id": 1,
"name": "Engineering",
"count": 32,
"selected": false,
"sub_tags": [
{
"id": 5,
"name": "Maintenance Engineer",
"count": 18,
"selected": false
},
{
"id": 6,
"name": "Service Technician",
"count": 8,
"selected": false
}
]
}
],
"languages": [
{
"code": "en",
"name": "English",
"count": 38,
"selected": false
}
]
}
}
}The tags facet uses a hierarchical structure where main categories contain nested sub_tags. When filtering by a main tag, all its sub-tags are automatically included.
Notes
- Only active publications from the website channel are returned
- Results are sorted by
published_atdescending by default - The list view does not include full job descriptions, requirements, or offers — use the detail endpoint for complete vacancy information
- When filtering by a main tag, all its sub-tags are automatically included (cascade filtering)
- Salary amounts are in the base currency unit (e.g., 3500 = €3,500)
- Compensation salary comes from the vacancy's own fields; hours fall back to the linked employment conditions (CompanyRemuneration) if the vacancy has no hours set
classificationis only present for tenants that have enabled vacancy classification (Settings → Vacancies); the key isnullwhen enabled but the vacancy has no label. It is not a filterable query parameter on this endpoint