REST API Dokumentation
Integrieren Sie Jobriver nahtlos in Ihr ATS, HR-System oder Ihre eigene Anwendung mit unserer leistungsstarken REST API.
API-Zugang anfragenÜbersicht
Die Jobriver REST API ermöglicht die programmatische Verwaltung Ihrer Stellenanzeigen. Integrieren Sie Jobriver in Ihr ATS, HR-System oder eigene Anwendungen.
Authentifizierung
Alle API-Anfragen erfordern einen gültigen API-Key im Header:
X-API-Key: jrv_abc123def456...
Berechtigungen
API-Keys können mit granularen Berechtigungen konfiguriert werden:
| Permission | Beschreibung |
|---|---|
read | Jobs auflisten und abrufen |
create | Neue Jobs erstellen |
update | Bestehende Jobs bearbeiten |
delete | Jobs löschen |
- API-Keys niemals im Frontend-Code speichern
- Umgebungsvariablen für Keys verwenden
- IP-Whitelisting im Dashboard aktivieren
- Nach 5 fehlgeschlagenen Versuchen: 1 Min. Sperre
Base URL & Endpoints
https://dev.jobriver.de/api/v1/
| Methode | Endpoint | Beschreibung | Permission |
|---|---|---|---|
| GET | /status | API-Status & Key-Info | - |
| GET | /jobs | Jobs auflisten | read |
| GET | /jobs/{id} | Einzelnen Job abrufen | read |
| POST | /jobs | Job erstellen | create |
| PUT/PATCH | /jobs/{id} | Job aktualisieren | update |
| DELETE | /jobs/{id} | Job löschen | delete |
Rate Limiting
Standard: 60 Requests pro Minute (erweiterbar)
Response Headers
X-RateLimit-Limit | Maximale Requests pro Minute |
X-RateLimit-Remaining | Verbleibende Requests |
X-RateLimit-Reset | Unix-Timestamp für Reset |
X-Request-Id | Eindeutige Request-ID (für Support) |
Bei Überschreitung: HTTP 429 mit Retry-After Header.
Endpoints im Detail
GET /api/v1/status
Gibt API-Status und Informationen zum verwendeten API-Key zurück.
Request
curl -X GET "https://dev.jobriver.de/api/v1/status" \
-H "X-API-Key: jrv_abc123..."
Response (200 OK)
{
"success": true,
"data": {
"api_version": "v1",
"status": "ok",
"key": {
"name": "Production API Key",
"prefix": "jrv_abc1",
"status": "active",
"permissions": ["read", "create", "update", "delete"],
"created_at": "2024-01-15T10:00:00Z",
"expires_at": null
},
"company": {
"id": 42,
"name": "TechStartup GmbH",
"slug": "techstartup-gmbh"
},
"limits": {
"rate_limit": {
"requests_per_minute": 60,
"remaining": 58,
"reset": 1707134520
},
"job_limit": {
"limit": 100,
"current_active_jobs": 23,
"unlimited": false
}
},
"usage": {
"requests_total": 4523,
"requests_today": 127,
"jobs_created": 45,
"last_request_at": "2024-02-05T14:30:00Z",
"last_request_ip": "192.168.1.100"
},
"ip_whitelist": ["192.168.1.0/24"],
"server_time": "2024-02-05T14:35:00+01:00"
},
"meta": {
"rate_limit": {
"limit": 60,
"remaining": 58,
"reset": 1707134520
}
}
}
GET /api/v1/jobs
Listet alle Jobs des Unternehmens mit Pagination und Filteroptionen.
Query Parameter
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
page | integer | 1 | Seitennummer (min: 1) |
per_page | integer | 20 | Items pro Seite (max: 100) |
is_active | boolean | - | Filter: true oder false |
category_id | integer | - | Filter nach Kategorie-ID |
search | string | - | Suche in Titel/Beschreibung (max: 100 Zeichen) |
Request
curl -X GET "https://dev.jobriver.de/api/v1/jobs?page=1&per_page=10&is_active=true" \
-H "X-API-Key: jrv_abc123..."
Response (200 OK)
{
"success": true,
"data": {
"jobs": [
{
"id": 123,
"slug": "senior-backend-developer",
"title": "Senior Backend Developer",
"description": "Wir suchen einen erfahrenen Backend Developer...",
"requirements": "Mindestens 5 Jahre Erfahrung mit PHP...",
"benefits": "Flexible Arbeitszeiten, Remote-Option...",
"location": "Berlin, Germany",
"location_type": "hybrid",
"employment_type": "fulltime",
"experience_level": "senior",
"category": {
"id": 5,
"name": "Software Development",
"slug": "software-development"
},
"salary": {
"min": 65000,
"max": 85000,
"currency": "EUR"
},
"technologies": [
{"id": 1, "name": "PHP", "slug": "php", "category": "backend"},
{"id": 2, "name": "Laravel", "slug": "laravel", "category": "backend"},
{"id": 3, "name": "MariaDB", "slug": "mariadb", "category": "database"}
],
"apply_type": "internal",
"apply_url": null,
"apply_email": null,
"is_featured": false,
"is_active": true,
"applications_count": 12,
"start_date": "2024-03-01",
"languages_required": ["Deutsch", "Englisch"],
"soft_skills": ["Teamfähigkeit", "Kommunikation"],
"published_at": "2024-02-01T10:00:00Z",
"expires_at": null,
"created_at": "2024-02-01T09:30:00Z",
"updated_at": "2024-02-05T14:00:00Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 10,
"total": 23,
"total_pages": 3
}
},
"meta": {
"rate_limit": { "limit": 60, "remaining": 57, "reset": 1707134520 }
}
}
GET /api/v1/jobs/{id}
Gibt einen einzelnen Job zurück.
Request
curl -X GET "https://dev.jobriver.de/api/v1/jobs/123" \
-H "X-API-Key: jrv_abc123..."
Response
Einzelnes Job-Objekt (gleiche Struktur wie bei der Auflistung).
POST /api/v1/jobs
Erstellt einen neuen Job.
Pflichtfelder
| Feld | Typ | Validierung |
|---|---|---|
title | string | 3-255 Zeichen |
description | string | min. 50 Zeichen |
location | string | max. 255 Zeichen |
Optionale Felder
| Feld | Typ | Erlaubte Werte |
|---|---|---|
requirements | string | max. 65535 Zeichen |
benefits | string | max. 65535 Zeichen |
location_type | enum | onsite, remote, hybrid |
employment_type | enum | fulltime, parttime, contract, freelance, internship |
experience_level | enum | junior, mid, senior, lead, any |
category_id | integer | Gültige Kategorie-ID |
salary_min | integer | 0 - 1.000.000 EUR |
salary_max | integer | ≥ salary_min |
technologies | array | Array von Technologie-IDs |
apply_type | enum | internal, external, email |
apply_url | string | Pflicht wenn apply_type = external |
apply_email | string | Pflicht wenn apply_type = email |
start_date | string | Format: YYYY-MM-DD |
languages_required | array | ["Deutsch", "Englisch"] |
soft_skills | array | ["Teamfähigkeit", ...] |
is_featured | boolean | Default: false |
is_active | boolean | Default: true |
Request
curl -X POST "https://dev.jobriver.de/api/v1/jobs" \
-H "Content-Type: application/json" \
-H "X-API-Key: jrv_abc123..." \
-d '{
"title": "Senior Backend Developer",
"description": "Wir suchen einen erfahrenen Backend Developer mit mindestens 5 Jahren Berufserfahrung in PHP. Sie werden an der Entwicklung unserer Kernplattform arbeiten und eng mit dem Frontend-Team zusammenarbeiten.",
"location": "Berlin, Germany",
"location_type": "hybrid",
"employment_type": "fulltime",
"experience_level": "senior",
"category_id": 5,
"salary_min": 65000,
"salary_max": 85000,
"technologies": [1, 2, 3],
"apply_type": "internal",
"start_date": "2024-03-15",
"languages_required": ["Deutsch", "Englisch"],
"soft_skills": ["Teamfähigkeit", "Kommunikation"],
"is_active": true
}'
Response (201 Created)
{
"success": true,
"data": {
"id": 456,
"slug": "senior-backend-developer-2",
"title": "Senior Backend Developer",
...
}
}
Validation Error (422)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"errors": {
"title": "Title must be at least 3 characters",
"description": "Description must be at least 50 characters",
"salary_min": "salary_min cannot be greater than salary_max"
}
}
}
}
PUT /api/v1/jobs/{id}
Aktualisiert einen bestehenden Job. Partial Updates sind möglich - nur die übergebenen Felder werden aktualisiert.
Request
curl -X PUT "https://dev.jobriver.de/api/v1/jobs/123" \
-H "Content-Type: application/json" \
-H "X-API-Key: jrv_abc123..." \
-d '{
"salary_min": 70000,
"salary_max": 90000,
"is_featured": true
}'
Response (200 OK)
Gibt das aktualisierte Job-Objekt zurück.
DELETE /api/v1/jobs/{id}
Löscht einen Job permanent. Diese Aktion kann nicht rückgängig gemacht werden.
Request
curl -X DELETE "https://dev.jobriver.de/api/v1/jobs/123" \
-H "X-API-Key: jrv_abc123..."
Response (200 OK)
{
"success": true,
"data": {
"deleted": true,
"job_id": 123
}
}
Datenmodell
Job-Objekt
| Feld | Typ | Beschreibung |
|---|---|---|
id | integer | Eindeutige Job-ID |
slug | string | URL-freundlicher Identifier |
title | string | Job-Titel |
description | string | Vollständige Beschreibung |
requirements | string|null | Anforderungen |
benefits | string|null | Benefits |
location | string | Arbeitsort |
location_type | enum | onsite, remote, hybrid |
employment_type | enum | fulltime, parttime, etc. |
experience_level | enum | junior, mid, senior, lead, any |
category | object | {id, name, slug} |
salary | object | {min, max, currency} |
technologies | array | [{id, name, slug, category}] |
apply_type | enum | internal, external, email |
is_active | boolean | Veröffentlichungsstatus |
is_featured | boolean | Hervorgehoben |
applications_count | integer | Anzahl Bewerbungen |
created_at | datetime | ISO 8601 Format |
updated_at | datetime | ISO 8601 Format |
Vollständiges Beispiel
{
"id": 123,
"slug": "senior-backend-developer",
"title": "Senior Backend Developer",
"description": "Wir suchen einen erfahrenen Backend Developer...",
"requirements": "Mindestens 5 Jahre Erfahrung mit PHP...",
"benefits": "Flexible Arbeitszeiten, Remote-Option...",
"location": "Berlin, Germany",
"location_type": "hybrid",
"employment_type": "fulltime",
"experience_level": "senior",
"category": {
"id": 5,
"name": "Software Development",
"slug": "software-development"
},
"salary": {
"min": 65000,
"max": 85000,
"currency": "EUR"
},
"technologies": [
{"id": 1, "name": "PHP", "slug": "php", "category": "backend"},
{"id": 2, "name": "Laravel", "slug": "laravel", "category": "backend"}
],
"apply_type": "internal",
"apply_url": null,
"apply_email": null,
"is_featured": false,
"is_active": true,
"applications_count": 12,
"start_date": "2024-03-01",
"languages_required": ["Deutsch", "Englisch"],
"soft_skills": ["Teamfähigkeit", "Kommunikation"],
"published_at": "2024-02-01T10:00:00Z",
"expires_at": null,
"created_at": "2024-02-01T09:30:00Z",
"updated_at": "2024-02-05T14:00:00Z"
}
Error Codes
Alle Fehler folgen diesem Format:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Beschreibung des Fehlers",
"details": {}
}
}
Authentifizierung (4xx)
| Code | HTTP | Beschreibung |
|---|---|---|
MISSING_API_KEY | 401 | X-API-Key Header fehlt |
INVALID_API_KEY | 403 | API-Key ungültig oder nicht gefunden |
API_KEY_INACTIVE | 403 | API-Key ist deaktiviert |
API_KEY_REVOKED | 403 | API-Key wurde widerrufen |
API_KEY_EXPIRED | 403 | API-Key ist abgelaufen |
API_KEY_BLOCKED | 403 | Temporär gesperrt (zu viele Fehlversuche) |
IP_NOT_ALLOWED | 403 | IP nicht in der Whitelist |
PERMISSION_DENIED | 403 | Fehlende Berechtigung für diese Aktion |
Rate Limiting
| Code | HTTP | Beschreibung |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Zu viele Anfragen. Retry-After Header beachten. |
Validierung & Ressourcen
| Code | HTTP | Beschreibung |
|---|---|---|
VALIDATION_ERROR | 422 | Eingabedaten ungültig. Details in errors. |
INVALID_JOB_ID | 400 | Job-ID fehlt oder ungültig |
JOB_NOT_FOUND | 404 | Job nicht gefunden |
JOB_LIMIT_EXCEEDED | 403 | Maximale Anzahl aktiver Jobs erreicht |
INVALID_REQUEST_BODY | 400 | Request Body fehlt oder kein gültiges JSON |
INVALID_CONTENT_TYPE | 415 | Content-Type muss application/json sein |
METHOD_NOT_ALLOWED | 405 | HTTP-Methode nicht erlaubt |
Server-Fehler (5xx)
| Code | HTTP | Beschreibung |
|---|---|---|
INTERNAL_ERROR | 500 | Interner Serverfehler |
UPDATE_FAILED | 500 | Job konnte nicht aktualisiert werden |
DELETE_FAILED | 500 | Job konnte nicht gelöscht werden |
Code-Beispiele
cURL (Bash)
# Jobs auflisten
curl -X GET "https://dev.jobriver.de/api/v1/jobs?is_active=true&per_page=10" \
-H "X-API-Key: jrv_abc123..."
# Job erstellen
curl -X POST "https://dev.jobriver.de/api/v1/jobs" \
-H "Content-Type: application/json" \
-H "X-API-Key: jrv_abc123..." \
-d '{"title":"PHP Developer","description":"Mindestens 50 Zeichen lange Beschreibung...","location":"Berlin"}'
JavaScript (fetch)
const API_KEY = 'jrv_abc123...';
const BASE_URL = 'https://dev.jobriver.de/api/v1';
// Jobs abrufen
async function getJobs() {
const res = await fetch(`${BASE_URL}/jobs?is_active=true`, {
headers: { 'X-API-Key': API_KEY }
});
const { success, data, error } = await res.json();
if (!success) {
console.error('API Error:', error.code, error.message);
return [];
}
return data.jobs;
}
// Job erstellen
async function createJob(jobData) {
const res = await fetch(`${BASE_URL}/jobs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify(jobData)
});
return await res.json();
}
PHP (cURL)
<?php
$apiKey = 'jrv_abc123...';
$baseUrl = 'https://dev.jobriver.de/api/v1';
// Jobs abrufen
function getJobs(): array {
global $apiKey, $baseUrl;
$ch = curl_init("$baseUrl/jobs?is_active=true&per_page=20");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: $apiKey"]
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response['success'] ? $response['data']['jobs'] : [];
}
// Job erstellen
function createJob(array $data): array {
global $apiKey, $baseUrl;
$ch = curl_init("$baseUrl/jobs");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: $apiKey"
]
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response;
}
Python (requests)
import requests
API_KEY = 'jrv_abc123...'
BASE_URL = 'https://dev.jobriver.de/api/v1'
headers = {'X-API-Key': API_KEY}
# Jobs abrufen
response = requests.get(f'{BASE_URL}/jobs', headers=headers, params={
'is_active': 'true',
'per_page': 20
})
data = response.json()
if data['success']:
jobs = data['data']['jobs']
for job in jobs:
print(f"{job['id']}: {job['title']}")
# Job erstellen
new_job = {
'title': 'Python Developer',
'description': 'Wir suchen einen erfahrenen Python Developer mit mindestens 3 Jahren Erfahrung...',
'location': 'München',
'location_type': 'remote',
'employment_type': 'fulltime',
'salary_min': 55000,
'salary_max': 75000
}
response = requests.post(
f'{BASE_URL}/jobs',
headers={**headers, 'Content-Type': 'application/json'},
json=new_job
)
result = response.json()
- Webhooks für Bewerbungs-Events
- Batch-Operationen (mehrere Jobs gleichzeitig)
- Bewerbungen über API abrufen