Updated April 22, 2026
/api/v1/vacancies/facets
curl -X GET \
"https://app.recruitsome.com/api/v1/vacancies/facets" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const response = await fetch('https://app.recruitsome.com/api/v1/vacancies/facets', {
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/facets');
$data = $response->json();
Get Vacancy Facets
The facets endpoint provides aggregated data about available filter options for vacancies. This is ideal for building dynamic search interfaces with faceted navigation, showing users what filters are available and how many results each filter would return.
Overview
This endpoint returns counts for all available filter options while respecting any currently applied filters. It's more efficient than using ?include=facets on the main listing endpoint when you only need facet data without the actual vacancy listings.
Simple Example
Get all available facets without any filters:
``bash cURL
curl -X GET https://app\.recruitsome\.com/api/v1/vacancies/facets \
-H "Authorization: Bearer YOUR_API_KEY"
javascript JavaScript
const response = await fetch('https://app\.recruitsome\.com/api/v1/vacancies/facets', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const facets = await response.json();
python Python
import requests
response = requests.get(
'https://app\.recruitsome\.com/api/v1/vacancies/facets',
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
facets = response.json()
Response Example
json
{
"data": {
"locations": [
{
"id": 1,
"name": "Amsterdam",
"city": "Amsterdam",
"country_code": "NL",
"country_name": "Netherlands",
"count": 45,
"selected": false
},
{
"id": 2,
"name": "Rotterdam",
"city": "Rotterdam",
"country_code": "NL",
"country_name": "Netherlands",
"count": 23,
"selected": false
},
{
"id": 3,
"name": "Utrecht",
"city": "Utrecht",
"country_code": "NL",
"country_name": "Netherlands",
"count": 18,
"selected": false
}
],
"company_locations": [
{
"id": 10,
"name": "Shell Pernis Refinery",
"city": "Rotterdam",
"country_code": "NL",
"country_name": "Netherlands",
"count": 12,
"selected": false
},
{
"id": 11,
"name": "ASML Veldhoven HQ",
"city": "Veldhoven",
"country_code": "NL",
"country_name": "Netherlands",
"count": 8,
"selected": false
}
],
"departments": [
{
"id": 5,
"name": "Engineering",
"count": 32,
"selected": false
},
{
"id": 6,
"name": "Sales",
"count": 21,
"selected": false
},
{
"id": 7,
"name": "Marketing",
"count": 15,
"selected": false
}
],
"experience_levels": [
{
"id": 2,
"name": "Junior",
"count": 20,
"selected": false
},
{
"id": 3,
"name": "Medior",
"count": 35,
"selected": false
},
{
"id": 4,
"name": "Senior",
"count": 28,
"selected": false
}
],
"job_types": [
{
"id": 1,
"name": "Full-time",
"count": 68,
"selected": false
},
{
"id": 2,
"name": "Part-time",
"count": 12,
"selected": false
},
{
"id": 3,
"name": "Contract",
"count": 8,
"selected": false
}
],
"education_levels": [
{
"id": 8,
"name": "Bachelor",
"count": 45,
"selected": false
},
{
"id": 9,
"name": "Master",
"count": 28,
"selected": false
}
],
"tags": [
{
"id": 1,
"name": "Engineering",
"count": 42,
"selected": false,
"sub_tags": [
{
"id": 5,
"name": "Software Engineer",
"count": 25,
"selected": false
},
{
"id": 6,
"name": "DevOps Engineer",
"count": 12,
"selected": false
}
]
},
{
"id": 2,
"name": "Sales",
"count": 28,
"selected": false,
"sub_tags": [
{
"id": 10,
"name": "Account Executive",
"count": 15,
"selected": false
}
]
}
],
"languages": [
{
"code": "en",
"name": "English",
"count": 52,
"selected": false
},
{
"code": "nl",
"name": "Nederlands",
"count": 34,
"selected": false
}
]
},
"meta": {
"generated_at": "2024-01-20T10:30:00Z",
"filters_applied": []
}
}
Filtered Example
Get facets with active filters to see how selections affect other options:
bash cURL
curl -X GET "https://app\.recruitsome\.com/api/v1/vacancies/facets?\
location_id[]=1&\
language=en" \
-H "Authorization: Bearer YOUR_API_KEY"
javascript JavaScript
const params = new URLSearchParams({
'location_id[]': 1,
'language': 'en'
});
const response = await fetch(
https://app\.recruitsome\.com/api/v1/vacancies/facets?${params},
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
const facets = await response.json();
python Python
import requests
params = {
'location_id[]': 1,
'language': 'en'
}
response = requests.get(
'https://app\.recruitsome\.com/api/v1/vacancies/facets',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params=params
)
facets = response.json()
javascriptselectedWhen filters are applied:
- The
field showstruefor active filtersfilters_appliedCounts in other facet categories are updated to reflect only the filtered results The array in meta shows which filters are activecompany_location_idQuery Parameters
Parameter Type Required Description language string No Filter by language code (e.g., 'en', 'nl', 'de') location_id[] array No Filter by location IDs (supports multiple) company_location_id[] array No Filter by company location IDs (work site, for agency tenants) department_id[] array No Filter by department IDs (supports multiple) search string No Search in title and summary experience_levels[] array No Filter by experience level IDs education_levels[] array No Filter by education level IDs job_types[] array No Filter by job type IDs tags[] array No Filter by tag IDs (main tags cascade to include sub-tags) <div class="not-prose rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800"><p class="mt-1 text-sm text-gray-700 dark:text-gray-300">The
parameter supports array notation on both this endpoint and the main vacancies endpoint.location_idanddepartment_idsupport array notation only on this facets endpoint.</p></div>"selected": trueUnderstanding Facet Counts
Without Filters
When no filters are applied, each facet shows the total count of active vacancies with that attribute:
- Location "Amsterdam" count: 45 = Total active vacancies in Amsterdam
- Department "Engineering" count: 32 = Total active vacancies in Engineering
With Active Filters
When filters are applied, counts show how many results match both the facet AND the current filters:
- If filtering by Amsterdam: Department "Engineering" count: 12 = Vacancies in Amsterdam AND Engineering
- The Amsterdam location itself will show
cityResponse Structure
Facet Object Structure
Each facet type contains an array of options with:
Field Type Description id integer Unique identifier for the option name string Human-readable name (translated) count integer Number of vacancies with this attribute selected boolean Whether this filter is currently active Location Facets
Location facets include additional geographic information:
Field Type Description id integer Unique location identifier name string Location name city string\ null City name (from locality field) country_code string\ null ISO 3166-1 alpha-2 country code country_name string\ null Full country name in current locale count integer Number of vacancies at this location selected boolean Whether this filter is currently active <div class="not-prose rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800"><p class="mt-1 text-sm text-gray-700 dark:text-gray-300">For remote positions or locations without a specific city, the
field may benull.</p></div>company_locationsCompany Location Facets
Company location facets represent the actual work sites (client company locations) for agency tenants. This array will be empty for non-agency tenants or when no vacancies have a company location assigned.
Field Type Description id integer Unique company location identifier name string Company location name city string\ null City name (from locality field) country_code string\ null ISO 3166-1 alpha-2 country code country_name string\ null Full country name in current locale count integer Number of vacancies at this work site selected boolean Whether this filter is currently active <div class="not-prose rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800"><p class="mt-1 text-sm text-gray-700 dark:text-gray-300">The
facet does not include the company name to prevent accidental disclosure of client relationships. Use theinclude_company_nameparameter on the vacancy list/detail endpoints if you need company names.</p></div>sub_tagsTags Facets (Hierarchical)
Tags facets use a hierarchical structure with main categories containing nested sub-tags:
Field Type Description id integer Unique tag identifier name string Tag name (translated) count integer Total vacancies in this category (including sub-tags) selected boolean Whether this filter is currently active sub_tags array Array of sub-category tags Each
item contains:id,name,count, andselected.<div class="not-prose rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800"><p class="mt-1 text-sm text-gray-700 dark:text-gray-300">When filtering by a main tag (e.g., "Engineering"), all vacancies tagged with any of its sub-tags are automatically included in the results.</p></div>
Language Facets
Language facets have a slightly different structure:
Field Type Description code string ISO 639-1 language code name string Language name count integer Number of vacancies in this language selected boolean Whether this filter is currently active Use Cases
Building Dynamic Filters
Use facet data to create filter interfaces that show available options and counts:
// Build location filter dropdown with enhanced geographic info
const locationFilter = facets.data.locations.map(location => ({
value: location.id,
label: ${location.name} (${location.count}),
description: location.city && location.country_name
? ${location.city}, ${location.country_name}
: location.country_name || '',
disabled: location.count === 0,
checked: location.selected
}));
// Example output:
// {
// value: 1,
// label: "Amsterdam Office (45)",
// description: "Amsterdam, Netherlands",
// disabled: false,
// checked: false
// }
Smart Filter Updates
When a user selects a filter, fetch updated facets to show how it affects other options:
javascript
async function onFilterChange(filters) {
// Fetch new facets with current filters
const facets = await fetchFacets(filters);
// Update UI to show new counts
updateFilterCounts(facets);
// Disable options with zero results
disableEmptyFilters(facets);
}
Pre-loading Filter Options
Load facets on page load to immediately show available filters:
javascript
// On page load
const [vacancies, facets] = await Promise.all([
fetchVacancies({ page: 1 }),
fetchFacets({})
]);
// Initialize filters with facet data
initializeFilters(facets);
Performance Considerations
- Caching: Facet data changes less frequently than vacancy listings, making it ideal for caching
- Parallel Loading: Fetch facets in parallel with initial vacancy data for faster page loads
- Debouncing: When implementing live filter updates, debounce facet requests to avoid excessive API calls
- Conditional Updates: Only refetch facets when filters actually change
Error Responses
Invalid Filter Parameter
json
{
"message": "The given data was invalid.",
"errors": {
"location_id.0": ["The location_id.0 must be a valid location."]
}
}
API Access Disabled
json
{
"message": "API access is not enabled for this tenant."
}
``
Best Practices
- Cache Facet Results: Implement client-side caching with appropriate TTL
- Handle Empty States: Design UI to gracefully handle facets with zero counts
- Progressive Enhancement: Load initial page with basic filters, enhance with facet data
- Batch Updates: When multiple filters change, update them together in a single request
- Loading States: Show loading indicators while fetching updated facets