Skip to main content

Vacancy Details

NL EN

Updated July 1, 2026

GET /api/v1/vacancies/{slug}
curl -X GET \
  "https://app.recruitsome.com/api/v1/vacancies/{slug}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
const response = await fetch('https://app.recruitsome.com/api/v1/vacancies/{slug}', {
  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/{slug}');

$data = $response->json();

Retrieve full details for a specific vacancy publication — everything your career website needs to render a complete vacancy page: full job texts, media, hiring manager, and (optionally) compensation.

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.

Path parameters

ParameterTypeDescription
slugstringThe publication slug (URL-friendly identifier), exactly as returned by the list endpoint

Query parameters

ParameterTypeDefaultDescription
languagestring-ISO 639-1 language code (e.g., nl, en). Sets the locale for translated fields like education levels, job types, and the work arrangement label.
include_compensationbooleanfalseInclude compensation details
include_mediaboolean-Accepted but has no effect on this endpoint: header_image and images are always included in the detail response. (The flag only matters on the list endpoint.)
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 (incremented on each request)
header_imageobject|nullHeader image URLs in multiple sizes (legacy, mapped to the default crop). Always included on this endpoint.
imagesobjectMap of all configured image crops. Always included on this endpoint.
job_descriptionstringFull job description (HTML)
job_requirementsstringJob requirements (HTML)
job_offerstringWhat the company offers (HTML)
company_descriptionstring|nullCompany description in the vacancy's language (falls back to the source description)
locationobject|nullLocation details (office/branch location)
company_locationobject|nullCompany location details (actual work site, for agency tenants)
departmentobject|nullDepartment details
hiring_managerobject|nullHiring manager information
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 for this vacancy. Key is absent unless the tenant has enabled vacancy classification; null when enabled but no label is assigned.
language_proficienciesarray|nullRequired language skills. null when no language requirements are set (not an empty array).
application_urlstringURL to apply for this position
metadataobjectAdditional vacancy metadata
compensationobjectCompensation details. Key is absent unless include_compensation=true.

Object structures

Images object

Returns a map of all configured image crops. The default key corresponds to the legacy header_image URL. 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"
  }
}

Header image object (legacy)

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"
}

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 query parameter). This key is omitted entirely when the vacancy has no work arrangement set.

Tag object

JSON
{
  "id": 5,
  "name": "Maintenance 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 at creation. It never changes when the label is renamed, so match on key — not name — when you build logic around a classification. color is one of a fixed palette (rose, amber, emerald, sky, violet, gray) or null.

Language proficiency object

JSON
{
  "language_code": "en",
  "speaking_level": "Professional",
  "reading_level": "Professional",
  "writing_level": "Professional"
}

Metadata object

JSON
{
  "status": "active"
}

Compensation object (when include_compensation=true)

The compensation object can contain salary, hours, holidays, and additional info:

  • salary: from the vacancy's own fields (min/max in the base currency unit, currency, period)
  • hours: from the vacancy's own fields, falling back to the linked employment conditions (CompanyRemuneration)
  • holidays: from the linked employment conditions (CompanyRemuneration). All day values are floats — partial days like 12.5 occur.
  • additional_info: free-text notes captured on the vacancy, with optional specialty_benefits and compensation_notes keys
JSON
{
  "salary": {
    "min": 3500,
    "max": 5000,
    "currency": "EUR",
    "period": "monthly"
  },
  "hours": {
    "min_per_week": 32,
    "max_per_week": 40
  },
  "holidays": {
    "total_days": 38.5,
    "breakdown": {
      "statutory": 20,
      "non_statutory": 5.5,
      "adv": 13
    }
  },
  "additional_info": {
    "specialty_benefits": "Company van and toolkit provided for on-call shifts.",
    "compensation_notes": "Salary depends on relevant certifications (VCA, NEN 3140)."
  }
}

Each section is omitted when no data is available: a vacancy with no salary set has no salary key, and zero-value entries are dropped from the holidays.breakdown.

Structured employment conditions such as pension, holiday allowance, thirteenth month, travel allowance, and work-from-home allowance are not exposed via the API. Anything beyond salary, hours, and holidays only surfaces as free text in additional_info when it has been captured on the vacancy.

Example

curl -X GET "https://app.recruitsome.com/api/v1/vacancies/maintenance-engineer?include_compensation=true&language=nl" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
const response = await fetch(
  'https://app.recruitsome.com/api/v1/vacancies/maintenance-engineer?include_compensation=true&language=nl',
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Accept': 'application/json'
    }
  }
);

const vacancy = 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,
    "header_image": {
      "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": {
      "default": {
        "url": "https://app.recruitsome.com/media/vacancies/412/header-large.jpg",
        "width": 1200,
        "height": 675,
        "mime_type": "image/jpeg"
      }
    },
    "job_description": "<h2>About the role</h2><p>As Maintenance Engineer you keep three production lines running...</p>",
    "job_requirements": "<h2>Requirements</h2><ul><li>Completed MBO 4 in mechatronics</li><li>VCA certificate</li></ul>",
    "job_offer": "<h2>What we offer</h2><ul><li>Salary between €3,500 and €5,000</li><li>38.5 vacation days</li></ul>",
    "company_description": "<p>We are a Rotterdam-based production company with 240 employees...</p>",
    "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": "Hybride"
    },
    "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"
    },
    "language_proficiencies": [
      {
        "language_code": "en",
        "speaking_level": "Professional",
        "reading_level": "Professional",
        "writing_level": "Professional"
      }
    ],
    "compensation": {
      "salary": {
        "min": 3500,
        "max": 5000,
        "currency": "EUR",
        "period": "monthly"
      },
      "hours": {
        "min_per_week": 32,
        "max_per_week": 40
      },
      "holidays": {
        "total_days": 38.5,
        "breakdown": {
          "statutory": 20,
          "non_statutory": 5.5,
          "adv": 13
        }
      }
    },
    "application_url": "https://www.yourcompany.com/vacatures/maintenance-engineer",
    "metadata": {
      "status": "active"
    }
  }
}

Error responses

StatusWhenFix
401Missing or invalid API keySend a valid key as Authorization: Bearer YOUR_API_KEY
403API key lacks the vacancies:read scopeAdd the scope to your key or regenerate it with the Career website preset
404No active website publication exists for this slugCheck the slug against the list endpoint — expired or unpublished vacancies also return 404
422Invalid query parameter (e.g. language not exactly 2 characters)Correct the parameter per the table above

Notes

  • The views_count is incremented with each request to this endpoint
  • header_image and images are always included on this endpoint — include_media has no effect here
  • Core relationship fields (location, company_location, department, hiring_manager) are always present, even when null; work_arrangement and compensation keys are omitted when not applicable
  • 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 assigned. Match integrations on the stable key, which survives label renames
  • Salary amounts are in the base currency unit (e.g., 3500 = €3,500)

Localization

When the language parameter is provided, the following fields are returned in the specified language:

  • education_levels[].name — translated education level names (e.g., "Middelbaar onderwijs" for Dutch)
  • job_types[].name — translated job type names (e.g., "Voltijd" for Dutch)
  • work_arrangement.label — translated work model label (e.g., "Hybride" for Dutch)

If no language parameter is provided, the API returns values in the application's default locale.