Skip to main content

Sollicitatie indienen

NL EN

Bijgewerkt 22 april 2026

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

$data = $response->json();

Sollicitatie indienen

Het endpoint voor het indienen van sollicitaties stelt kandidaten in staat om te solliciteren op gepubliceerde vacatures door hun gegevens en ondersteunende documenten te versturen. Dit endpoint ondersteunt het uploaden van meerdere documenten, uitgebreide kandidaatprofielen en trackinginformatie.

Implementatiestrategie

Waarschuwing

Cruciaal implementatiepatroon: Sla sollicitaties altijd lokaal op vóór verzending en implementeer retry-logica. Netwerkfouten, rate limits of tijdelijke serverproblemen mogen nooit leiden tot verloren sollicitaties.

Aanbevolen implementatiestroom

graph TD

A[User Fills Form] --> B[Validate Locally]

B --> C[Store in Local Storage/DB]

C --> D[Submit to API]

D --> E{Response}

E -->|Success 201| F[Clear Local Storage]

E -->|Error 4xx/5xx| G[Keep in Queue]

G --> H[Retry with Backoff]

H --> D

  1. Valideer invoer lokaal vóór verzending
  2. Sla sollicitatiegegevens op in lokale opslag of database
  3. Toon de status aan de gebruiker
  4. Verstuur naar de API met correcte foutafhandeling
  5. Bij succes (201): Wis de lokale opslag en toon een bevestiging
  6. Bij een fout: Bewaar in de wachtrij en implementeer retry met exponentiële backoff

Eenvoudig voorbeeld

Dien een eenvoudige sollicitatie in met alleen de verplichte velden:

``bash cURL

curl -X POST https://app\.recruitsome\.com/api/v1/applications \

-H "Authorization: Bearer YOUR_API_KEY" \

-H "Content-Type: application/json" \

-d '{

"vacancy": "senior-software-engineer-amsterdam",

"candidate": {

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]"

}

}'


javascript JavaScript

const applicationData = {

vacancy: "senior-software-engineer-amsterdam",

candidate: {

given_name: "John",

family_name: "Doe",

email: "[email protected]"

}

};

// Sla eerst lokaal op

localStorage.setItem('pending_application', JSON.stringify(applicationData));

try {

const response = await fetch('https://app\.recruitsome\.com/api/v1/applications', {

method: 'POST',

headers: {

'Authorization': 'Bearer YOUR_API_KEY',

'Content-Type': 'application/json'

},

body: JSON.stringify(applicationData)

});

if (response.ok) {

localStorage.removeItem('pending_application');

const result = await response.json();

console.log('Application submitted:', result);

} else {

// Bewaar in local storage voor herpoging

throw new Error(Failed: ${response.status});

}

} catch (error) {

console.error('Submission failed, will retry:', error);

}


python Python

import requests

import json

application_data = {

"vacancy": "senior-software-engineer-amsterdam",

"candidate": {

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]"

}

}

Sla eerst lokaal op (voorbeeld met bestand)

with open('pending_application.json', 'w') as f:

json.dump(application_data, f)

try:

response = requests.post(

'https://app\.recruitsome\.com/api/v1/applications',

headers={

'Authorization': 'Bearer YOUR_API_KEY',

'Content-Type': 'application/json'

},

json=application_data

)

if response.status_code == 201:

# Gelukt - verwijder lokale opslag

import os

os.remove('pending_application.json')

print('Application submitted:', response.json())

else:

raise Exception(f'Failed: {response.status_code}')

except Exception as e:

print(f'Submission failed, will retry: {e}')



Voorbeeld van een response

json

{

"message": "Application submitted successfully",

"data": {

"id": 456,

"vacancy": {

"id": 123,

"slug": "senior-software-engineer-amsterdam",

"title": "Senior Software Engineer"

},

"candidate": {

"id": 789,

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]"

},

"status": "screening",

"source": "api",

"documents": [],

"submitted_at": "2024-01-20T14:30:00Z",

"created_at": "2024-01-20T14:30:00Z"

}

}

Aanbevolen voorbeeld

Dien een sollicitatie in met alle sterk aanbevolen velden voor de beste kans op succes:

bash cURL

curl -X POST https://app\.recruitsome\.com/api/v1/applications \

-H "Authorization: Bearer YOUR_API_KEY" \

-H "Content-Type: application/json" \

-d '{

"vacancy": "senior-software-engineer-amsterdam",

"candidate": {

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]",

"mobile_phone": "+31612345678"

},

"documents": {

"resume": {

"filename": "john_doe_resume.pdf",

"content": "JVBERi0xLjQKJeLj...",

"mime_type": "application/pdf"

}

},

"privacy_policy_accepted": true

}'


javascript JavaScript

// Bestand inlezen en converteren naar base64

async function fileToBase64(file) {

return new Promise((resolve, reject) => {

const reader = new FileReader();

reader.readAsDataURL(file);

reader.onload = () => {

const base64 = reader.result.split(',')[1];

resolve(base64);

};

reader.onerror = reject;

});

}

// Sollicitatie voorbereiden met cv

const resumeFile = document.getElementById('resume-input').files[0];

const resumeBase64 = await fileToBase64(resumeFile);

const applicationData = {

vacancy: "senior-software-engineer-amsterdam",

candidate: {

given_name: "John",

family_name: "Doe",

email: "[email protected]",

mobile_phone: "+31612345678"

},

documents: {

resume: {

filename: resumeFile.name,

content: resumeBase64,

mime_type: resumeFile.type

}

},

privacy_policy_accepted: true

};

// Opslaan en indienen met retry

async function submitWithRetry(data, attempt = 1) {

try {

const response = await fetch('https://app\.recruitsome\.com/api/v1/applications', {

method: 'POST',

headers: {

'Authorization': 'Bearer YOUR_API_KEY',

'Content-Type': 'application/json'

},

body: JSON.stringify(data)

});

if (response.ok) {

localStorage.removeItem('pending_application');

return await response.json();

} else if (response.status === 429 && attempt < 3) {

// Rate limited - opnieuw proberen met backoff

await new Promise(resolve => setTimeout(resolve, attempt * 2000));

return submitWithRetry(data, attempt + 1);

} else {

throw new Error(Mislukt: ${response.status});

}

} catch (error) {

localStorage.setItem('pending_application', JSON.stringify(data));

throw error;

}

}


python Python

import requests

import base64

import time

def submit_with_retry(data, attempt=1):

try:

response = requests.post(

'https://app\.recruitsome\.com/api/v1/applications',

headers={

'Authorization': 'Bearer YOUR_API_KEY',

'Content-Type': 'application/json'

},

json=data

)

if response.status_code == 201:

return response.json()

elif response.status_code == 429 and attempt < 3:

# Rate limited - opnieuw proberen met backoff

time.sleep(attempt * 2)

return submit_with_retry(data, attempt + 1)

else:

response.raise_for_status()

except Exception as e:

# Opslaan voor latere retry

with open('pending_application.json', 'w') as f:

json.dump(data, f)

raise

Cv-bestand inlezen

with open('resume.pdf', 'rb') as f:

resume_content = base64.b64encode(f.read()).decode('utf-8')

application_data = {

"vacancy": "senior-software-engineer-amsterdam",

"candidate": {

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]",

"mobile_phone": "+31612345678"

},

"documents": {

"resume": {

"filename": "john_doe_resume.pdf",

"content": resume_content,

"mime_type": "application/pdf"

}

},

"privacy_policy_accepted": True

}

result = submit_with_retry(application_data)

Volledig voorbeeld

Dien een uitgebreide sollicitatie in met alle beschikbare velden:

bash cURL

curl -X POST https://app\.recruitsome\.com/api/v1/applications \

-H "Authorization: Bearer YOUR_API_KEY" \

-H "Content-Type: application/json" \

-d '{

"vacancy": 123,

"candidate": {

"given_name": "John",

"family_name": "Doe",

"email": "[email protected]",

"mobile_phone": "+31612345678",

"fixed_phone": "+31201234567"

},

"documents": {

"resume": {

"filename": "john_doe_resume.pdf",

"content": "JVBERi0xLjQKJeLj...",

"mime_type": "application/pdf"

},

"cover_letter": {

"filename": "cover_letter.pdf",

"content": "JVBERi0xLjQKJeLj...",

"mime_type": "application/pdf"

},

"additional": [

{

"filename": "portfolio.pdf",

"content": "JVBERi0xLjQKJeLj...",

"mime_type": "application/pdf",

"description": "My design portfolio"

}

]

},

"privacy_policy_accepted": true,

"tracking": {

"ip_address": "192.168.1.100",

"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",

"referrer": "https://jobboard.com/jobs/123"

}

}'

Requestvelden

Verplichte velden

VeldTypeBeschrijving
vacancystring\integerVerplicht. Vacature-identificatie (slug, publication_slug of ID)
candidate.given_namestringVerplicht. Voornaam (max 255 tekens)
candidate.family_namestringVerplicht. Achternaam (max 255 tekens)
candidate.emailstringVerplicht. Geldig e-mailadres (max 255 tekens)

Sterk aanbevolen velden

<div class="not-prose rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-900/20"><p class="font-medium text-amber-800 dark:text-amber-300">Waarschuwing</p><p class="mt-1 text-sm text-amber-700 dark:text-amber-400">Sollicitaties zonder deze velden hebben een aanzienlijk lagere slagingskans en kunnen automatisch worden afgewezen door AI-screening.</p></div>

VeldTypeBeschrijving
documents.resumeobjectSterk aanbevolen. CV/resumédocument
candidate.mobile_phonestringSterk aanbevolen. Mobiel nummer in E.164-formaat (bijv. +31612345678)
privacy_policy_acceptedbooleanSterk aanbevolen. Expliciete toestemming voor gegevensverwerking

Optionele velden

VeldTypeBeschrijving
candidate.fixed_phonestringVast telefoonnummer in E.164-formaat
candidate.linkedin_urlstringLinkedIn-profiel-URL (max 255 tekens)
documents.cover_letterobjectMotivatiebrief
documents.additionalarrayMaximaal 5 aanvullende documenten
tracking.ip_addressstringIP-adres van de kandidaat
tracking.user_agentstringBrowser user agent (max 1000 tekens)
tracking.referrerstringVerwijzings-URL (max 1000 tekens)

Documenten uploaden

Documenten moeten base64-gecodeerd zijn en metadata bevatten:

Documentstructuur

json

{

"filename": "document.pdf",

"content": "base64_encoded_content_here",

"mime_type": "application/pdf"

}


Ondersteunde documenttypen

CategorieToegestane MIME-typesMax. grootte
CVapplication/pdf<br/>application/msword<br/>application/vnd.openxmlformats-officedocument.wordprocessingml.document5MB
MotivatiebriefZelfde als CV5MB
AanvullendZelfde als CV + image/jpeg, image/png20MB

<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">- Maximaal 5 aanvullende documenten

  • Maximale grootte van het totale verzoek: 30MB
  • Base64-codering vergroot de bestandsgrootte met ~33%</p></div>

Voorbeeld van document uploaden

javascript

// Helper function to convert file to base64

async function prepareDocument(file) {

return new Promise((resolve, reject) => {

const reader = new FileReader();

reader.readAsDataURL(file);

reader.onload = () => {

const base64 = reader.result.split(',')[1];

resolve({

filename: file.name,

content: base64,

mime_type: file.type

});

};

reader.onerror = reject;

});

}

// Process multiple files

const resumeFile = document.getElementById('resume').files[0];

const coverLetterFile = document.getElementById('cover-letter').files[0];

const additionalFiles = document.getElementById('additional').files;

const documents = {

resume: await prepareDocument(resumeFile),

cover_letter: coverLetterFile ? await prepareDocument(coverLetterFile) : undefined,

additional: []

};

// Add additional documents

for (let i = 0; i < Math.min(additionalFiles.length, 5); i++) {

documents.additional.push(await prepareDocument(additionalFiles[i]));

}


Telefoonnummerformaat

Telefoonnummers moeten in het internationale E.164-formaat zijn:

Geldige voorbeelden

  • +31612345678 (Nederlands mobiel)
  • +12125551234 (Amerikaans nummer)
  • +447911123456 (Brits mobiel)
  • +33612345678 (Frans mobiel)

Ongeldige voorbeelden

  • 0612345678 (landcode ontbreekt)
  • +31 6 1234 5678 (bevat spaties)
  • +31-6-12345678 (bevat streepjes)
  • (06) 12345678 (verkeerd formaat)

Hulpfunctie voor telefoonvalidatie

javascript

function validateE164(phone) {

const e164Regex = /^\+[1-9]\d{6,14}$/;

return e164Regex.test(phone);

}

function formatPhoneForE164(phone, countryCode = '31') {

// Remove all non-digits

let cleaned = phone.replace(/\D/g, '');

// Remove leading zeros

cleaned = cleaned.replace(/^0+/, '');

// Add country code if missing

if (!cleaned.startsWith(countryCode)) {

cleaned = countryCode + cleaned;

}

// Add + prefix

return '+' + cleaned;

}

// Examples

formatPhoneForE164('06-12345678', '31'); // +31612345678

formatPhoneForE164('(202) 555-1234', '1'); // +12025551234

Vacature-identificatie

Het vacancy veld accepteert drie typen identifiers:

  1. Numeriek ID: 123
  2. Vacature-slug: "senior-software-engineer"
  3. Publicatie-slug: "senior-software-engineer-amsterdam"

<div class="not-prose rounded-lg border border-emerald-200 bg-emerald-50 p-4 dark:border-emerald-800 dark:bg-emerald-900/20"><p class="font-medium text-emerald-800 dark:text-emerald-300">Tip</p><p class="mt-1 text-sm text-emerald-700 dark:text-emerald-400">Gebruik de publicatie-slug uit de vacaturelijst-API voor de meest betrouwbare matching.</p></div>

Foutafhandeling

Validatiefouten (422)

json

{

"message": "The given data was invalid.",

"errors": {

"candidate.email": [

"The candidate's email address is required."

],

"candidate.mobile_phone": [

"The candidate.mobile phone field must be a valid phone number."

],

"documents.resume": [

"The file size exceeds the maximum allowed limit."

]

}

}


Bedrijfslogicafouten

Vacature niet gevonden (404)

json

{

"message": "Vacancy not found",

"error": "VACANCY_NOT_FOUND"

}


Vacature gesloten (400)

json

{

"message": "This vacancy is no longer accepting applications",

"error": "VACANCY_CLOSED"

}


Rate Limiting (429)

json

{

"message": "Too many requests. Please try again later.",

"retry_after": 60

}


<div class="not-prose rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-900/20"><p class="font-medium text-amber-800 dark:text-amber-300">Waarschuwing</p><p class="mt-1 text-sm text-amber-700 dark:text-amber-400">Rate limit: 10 verzoeken per minuut per API key</p></div>

Best practices voor implementatie

1. Local Storage Pattern

javascript

class ApplicationQueue {

constructor() {

this.storageKey = 'pending_applications';

}

add(applicationData) {

const queue = this.getAll();

queue.push({

id: Date.now(),

data: applicationData,

attempts: 0,

lastAttempt: null

});

localStorage.setItem(this.storageKey, JSON.stringify(queue));

}

getAll() {

const stored = localStorage.getItem(this.storageKey);

return stored ? JSON.parse(stored) : [];

}

remove(id) {

const queue = this.getAll().filter(item => item.id !== id);

localStorage.setItem(this.storageKey, JSON.stringify(queue));

}

async processQueue() {

const queue = this.getAll();

for (const item of queue) {

if (item.attempts >= 3) continue; // Maximaal aantal pogingen bereikt

try {

await this.submit(item.data);

this.remove(item.id);

} catch (error) {

item.attempts++;

item.lastAttempt = Date.now();

this.update(item);

}

}

}

}


2. Validatie vóór verzending

javascript

function validateApplication(data) {

const errors = {};

// Verplichte velden

if (!data.candidate?.given_name?.trim()) {

errors['candidate.given_name'] = 'Voornaam is verplicht';

}

if (!data.candidate?.family_name?.trim()) {

errors['candidate.family_name'] = 'Achternaam is verplicht';

}

if (!data.candidate?.email || !isValidEmail(data.candidate.email)) {

errors['candidate.email'] = 'Een geldig e-mailadres is verplicht';

}

// Sterk aanbevolen velden

const warnings = {};

if (!data.documents?.resume) {

warnings.resume = 'Het toevoegen van een cv vergroot je kansen aanzienlijk';

}

if (!data.candidate?.mobile_phone) {

warnings.mobile_phone = 'Een mobiel nummer helpt recruiters om je snel te bereiken';

}

if (!data.privacy_policy_accepted) {

warnings.privacy = 'Je moet het privacybeleid accepteren';

}

return { errors, warnings, isValid: Object.keys(errors).length === 0 };

}


3. Voortgangsfeedback

javascript

class ApplicationSubmitter {

constructor(onProgress) {

this.onProgress = onProgress;

}

async submit(data) {

this.onProgress({ status: 'validating', progress: 10 });

const validation = validateApplication(data);

if (!validation.isValid) {

throw new ValidationError(validation.errors);

}

this.onProgress({ status: 'preparing', progress: 30 });

// Lokaal opslaan

this.onProgress({ status: 'saving_locally', progress: 40 });

localStorage.setItem('current_application', JSON.stringify(data));

// Verzenden

this.onProgress({ status: 'submitting', progress: 60 });

try {

const response = await fetch('/api/v1/applications', {

method: 'POST',

headers: {

'Authorization': Bearer ${API_KEY},

'Content-Type': 'application/json'

},

body: JSON.stringify(data)

});

this.onProgress({ status: 'processing_response', progress: 80 });

if (response.ok) {

localStorage.removeItem('current_application');

this.onProgress({ status: 'complete', progress: 100 });

return await response.json();

} else {

throw new SubmissionError(response.status, await response.text());

}

} catch (error) {

this.onProgress({ status: 'error', progress: 0, error });

throw error;

}

}

}


4. Duplicaatpreventie

javascript

function generateApplicationHash(data) {

const key = ${data.vacancy}_${data.candidate.email}_${Date.now()};

return btoa(key);

}

function isDuplicateSubmission(data, timeWindowMs = 60000) {

const hash = generateApplicationHash(data);

const submissions = JSON.parse(localStorage.getItem('recent_submissions') || '[]');

// Oude inzendingen opschonen

const cutoff = Date.now() - timeWindowMs;

const recent = submissions.filter(s => s.timestamp > cutoff);

// Controleren op duplicaat

if (recent.some(s => s.hash === hash)) {

return true;

}

// Nieuwe inzending toevoegen

recent.push({ hash, timestamp: Date.now() });

localStorage.setItem('recent_submissions', JSON.stringify(recent));

return false;

}

Je integratie testen

Testscenario's

  1. Succesgeval: Geldige sollicitatie met alle verplichte velden
  2. Validatiefouten: Ontbrekende verplichte velden, ongeldige formaten
  3. Netwerkfouten: Timeout, verbindingsfouten
  4. Rate limiting: Verstuur 11 verzoeken binnen een minuut
  5. Grote bestanden: Test met een cv van 5 MB
  6. Meerdere documenten: Test met cv + motivatiebrief + 5 extra bijlagen

Testdata

javascript

const testApplication = {

vacancy: "test-vacancy-slug",

candidate: {

given_name: "Test",

family_name: "User",

email: "[email protected]",

mobile_phone: "+31612345678"

},

documents: {

resume: {

filename: "test_resume.pdf",

content: "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFI+PgplbmRvYmoKMiAwIG9iago8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PgplbmRvYmoKMyAwIG9iago8PC9UeXBlL1BhZ2UvUGFyZW50IDIgMCBSL1Jlc291cmNlczw8L0ZvbnQ8PC9GMSA0IDAgUj4+Pj4vTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDUgMCBSPj4KZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9Gb250L1N1YnR5cGUvVHlwZTEvQmFzZUZvbnQvSGVsdmV0aWNhPj4KZW5kb2JqCjUgMCBvYmoKPDwvTGVuZ3RoIDQ0Pj4Kc3RyZWFtCkJUIC9GMSAxMiBUZiAxMDAgNzAwIFRkIChUZXN0IFJlc3VtZSkgVGogRVQKZW5kc3RyZWFtCmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYKMDAwMDAwMDAxNSAwMDAwMCBuCjAwMDAwMDAwNzQgMDAwMDAgbgowMDAwMDAwMTMxIDAwMDAwIG4KMDAwMDAwMDIyOSAwMDAwMCBuCjAwMDAwMDAzMDYgMDAwMDAgbgp0cmFpbGVyCjw8L1NpemUgNi9Sb290IDEgMCBSPj4Kc3RhcnR4cmVmCjQwMgolJUVPRg==",

mime_type: "application/pdf"

}

},

privacy_policy_accepted: true

};

``

Vergeet niet om persoonsgegevens te verwerken conform de AVG-vereisten. Verzamel alleen de noodzakelijke informatie en zorg ervoor dat de juiste toestemmingsmechanismen zijn ingericht.