Skip to main content

List Vacancies

NL EN

Updated July 1, 2026

GET /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

ParameterTypeDefaultDescription
pageinteger1Page number for pagination
per_pageinteger20Items per page (max: 100)
searchstring-Search in title and summary (case-insensitive)
languagestring-Filter by language code (exactly 2 characters, e.g. nl). Also sets the locale for translated fields.
location_idinteger-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_idinteger-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)
sortstringpublished_atSort field: published_at, title, created_at
sort_directionstringdescSort direction: asc or desc
includestring-Include additional data: facets
include_mediabooleanfalseInclude header_image and images
include_compensationbooleanfalseInclude basic compensation data
include_company_namebooleanfalseInclude company name in the company_location object (opt-in for privacy)

Response fields

FieldTypeDescription
idintegerUnique vacancy publication ID
slugstringURL-friendly identifier
titlestringVacancy title
summarystringBrief description (HTML)
languagestringLanguage code (ISO 639-1)
published_atstringISO 8601 publication date
ends_atstring|nullISO 8601 expiration date
views_countintegerNumber of times viewed
locationobject|nullLocation details (office/branch location)
company_locationobject|nullCompany location details (actual work site, for agency tenants)
departmentobject|nullDepartment details
hiring_managerobject|nullHiring manager details
education_levelsarrayRequired education levels (may be empty)
job_typesarrayEmployment types (may be empty)
experience_levelsarrayExperience/seniority levels (e.g., Junior, Medior, Senior, Lead; may be empty)
work_arrangementobjectWork model: on-site, hybrid, or remote. Key is absent when the vacancy has no work arrangement set.
tagsarrayJob category tags (main and sub-categories; may be empty)
classificationobject|nullThe 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_urlstringURL to apply for this position
metadataobjectAdditional vacancy metadata
header_imageobject|nullHeader image URLs. Key is absent unless include_media=true.
imagesobjectMap of all configured image crops. Key is absent unless include_media=true.
compensationobject|nullBasic 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

JSON
{
  "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.

JSON
{
  "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

JSON
{
  "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.

JSON
{
  "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

JSON
{
  "id": 1,
  "name": "Bachelor"
}

Job type object

JSON
{
  "id": 1,
  "name": "Full-time"
}

Experience level object

JSON
{
  "id": 3,
  "name": "Senior"
}

Possible values: Junior, Medior, Senior, Lead. Returns an empty array when no experience level is assigned.

Work arrangement object

JSON
{
  "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

JSON
{
  "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

JSON
{
  "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

JSON
{
  "status": "active"
}

Compensation object (when include_compensation=true)

Basic compensation summary for the list view:

JSON
{
  "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)

JSON
{
  "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.

JSON
{
  "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

JSON
{
  "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:

JSON
{
  "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_at descending 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
  • classification is only present for tenants that have enabled vacancy classification (Settings → Vacancies); the key is null when enabled but the vacancy has no label. It is not a filterable query parameter on this endpoint