Entwickler
Kostenlose Jobs-API
Alle aktiven Werkstudentenjobs und Praktika in Deutschland auf workingstudentjobs.de als JSON. Kostenlos, ohne API-Key, ohne Anmeldung, stündlich aktualisiert. Für Job-Apps, Forschung und KI-Agenten, die Studierenden bei der Jobsuche helfen.
Beta bis 31. Oktober 2026: Feldnamen und Werte können bis dahin noch korrigiert werden. Danach bekommt v1 nur noch Ergänzungen.
Maschinenlesbar:OpenAPI-3.1-Spezifikationllms.txt
Schnellstart
Eine GET-Anfrage liefert die 100 neuesten Jobs. Hänge an jede Anfrage ref=deineapp an, damit wir dich vor einer inkompatiblen Änderung erreichen können.
curl "https://www.workingstudentjobs.de/api/v1/jobs?city=berlin&type=working_student&limit=20&ref=myapp"// Walk every live job, pausing when rate limited.
let url = "https://www.workingstudentjobs.de/api/v1/jobs?limit=300&ref=myapp";
const jobs = [];
while (url) {
const res = await fetch(url);
if (res.status === 429) {
const wait = Number(res.headers.get("Retry-After") ?? 60);
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
continue;
}
if (!res.ok) throw new Error((await res.json()).error.message);
const page = await res.json();
jobs.push(...page.data);
url = page.links.next;
}import requests
res = requests.get(
"https://www.workingstudentjobs.de/api/v1/jobs",
params={"city": "munich", "language": "en", "ref": "myapp"},
timeout=30,
)
res.raise_for_status()
for job in res.json()["data"]:
company = job["company"]["name"] if job["company"] else ""
print(job["title"], company, job["apply_url"]){
"data": [
{
"id": "3f6c2a1e-8b4d-4e0a-9c7f-2d5e1b6a9f80",
"slug": "example-gmbh-working-student-data-analytics-3f6c2a1e",
"title": "Working Student Data Analytics (m/f/d)",
"url": "https://www.workingstudentjobs.de/jobs/example-gmbh-working-student-data-analytics-3f6c2a1e",
"apply_url": "https://www.workingstudentjobs.de/apply/3f6c2a1e-8b4d-4e0a-9c7f-2d5e1b6a9f80?ref=myapp",
"company": {
"name": "Example GmbH",
"slug": "example-gmbh",
"url": "https://www.workingstudentjobs.de/jobs/at/example-gmbh",
"logo_url": null,
"website_domain": "example.com"
},
"location": {
"city": "Berlin",
"city_slug": "berlin",
"state": "Berlin",
"state_code": "BE",
"country_code": "DE",
"postal_code": "10115",
"latitude": 52.52,
"longitude": 13.405
},
"types": [
"working_student"
],
"field": "tech",
"sub_field": "data",
"working_mode": "hybrid",
"salary": {
"min": 16,
"max": 18,
"currency": "EUR",
"period": "hour"
},
"skills": [
"SQL",
"Python",
"Tableau"
],
"languages": {
"german": "optional",
"english": "required"
},
"sponsored": false,
"details": {
"study_fields": [
"computer science",
"statistics"
],
"study_fields_or_comparable": true,
"study_levels": [
"bachelor",
"master"
],
"min_semester": 3,
"enrolment": "required",
"german_level": null,
"english_level": {
"level": "fluent",
"cefr": "C1"
},
"other_languages": [],
"hours_per_week": {
"min": 16,
"max": 20
},
"start": {
"asap": true,
"date": null
},
"duration_months": {
"min": 12,
"max": null
},
"internship_type": null,
"remote_days_max": 2,
"benefits": [
"flexible hours",
"public transport ticket"
],
"cover_letter": "not_needed",
"transcripts": null,
"prior_experience": "preferred"
},
"posted_at": "2026-10-16T07:12:40.000Z",
"first_seen_at": "2026-10-16T09:03:11.482Z",
"expires_at": null
}
],
"links": {
"self": "https://www.workingstudentjobs.de/api/v1/jobs?city=berlin&limit=1&ref=myapp",
"next": "https://www.workingstudentjobs.de/api/v1/jobs?city=berlin&limit=1&ref=myapp&cursor=..."
},
"meta": {
"limit": 1,
"count": 1,
"api_version": "1.0-beta"
}
}Endpunkte
| Endpunkt | Beschreibung |
|---|---|
| GET /api/v1/jobs | Aktive Jobs, neueste zuerst, mit Filtern und Cursor-Seiten. |
| GET /api/v1/jobs/{id} | Ein Job per ID. 301, wenn er mit einer anderen aktiven Anzeige zusammengeführt wurde, 410, wenn er geschlossen ist, 404, wenn es keinen öffentlichen Job mit dieser ID gibt. |
| GET /api/v1/cities | Alle Städte mit mindestens einem aktiven Job und deren Anzahl. Diese Slugs gelten für den Stadtfilter. |
| GET /openapi.json | Die OpenAPI-3.1-Beschreibung aller Endpunkte. |
Parameter für /api/v1/jobs
Alle optional. Filter werden mit UND verknüpft, kommagetrennte Werte innerhalb eines Filters mit ODER. Unbekannte Parameter werden ignoriert, ungültige Werte ergeben 400.
| Parameter | Beschreibung |
|---|---|
| limit | Jobs pro Seite, 1 bis 300. Standard 100. |
| cursor | Undurchsichtiges Seiten-Token. Folge links.next, statt es selbst zu bauen. |
| city | Stadt-Slugs, bis zu 20, z. B. berlin,munich. Deutsche Schreibweisen wie muenchen oder koeln funktionieren auch. Unbekannte Slugs ergeben 400 unknown_city. |
| field | Bereiche: tech, engineering, marketing, finance, operations, sales, hr, consulting, design, research, legal, logistics, education, healthcare, gastronomy-hospitality. |
| type | working_student, internship oder beides. Ein Job kann beides sein. |
| language | en: Englisch reicht, Deutsch wird nicht verlangt. de: Deutsch wird verlangt. |
| remote | Arbeitsmodelle: remote, hybrid, onsite. |
| since | Nur Jobs, die wir ab diesem ISO-8601-Datum oder -Zeitpunkt zuerst gesehen haben, z. B. 2026-10-15 oder 2026-10-15T08:00:00Z. |
| ref | Der Name deiner App, 1 bis 64 Zeichen aus Buchstaben, Ziffern, Punkt, Bindestrich oder Unterstrich. Bleibt an jeder apply_url erhalten. |
Felder eines Jobs
Jeder Job in data hat diese Felder. Null heißt, die Anzeige sagt nichts dazu, nie "nein".
| Feld | Beschreibung |
|---|---|
| id, slug, title | Feste ID (UUID), URL-Slug und Jobtitel. |
| url | Die Jobseite auf workingstudentjobs.de. |
| apply_url | Schicke Bewerber hierhin. Leitet zur Bewerbungsseite des Arbeitgebers weiter, oder zu unserer Jobseite, wenn der Arbeitgeber Bewerbungen per E-Mail annimmt oder der Job geschlossen ist. |
| company | Name, Slug, Unternehmensseite, Logo und Website-Domain. Null, wenn unbekannt. |
| location | Stadt, Slug, Bundesland, Postleitzahl und Koordinaten. Null bei Anzeigen ohne Stadt. |
| types | working_student und/oder internship. |
| field, sub_field | field ist einer der Bereiche oben, sub_field eine feinere Einordnung wie controlling. |
| working_mode | remote, hybrid oder onsite. Onsite, wenn die Anzeige nichts sagt. |
| salary | min, max, Währung und Zeitraum (hour, day, week, month, year). Null, wenn die Anzeige keine Vergütung nennt. |
| skills | In der Anzeige genannte Skills. |
| languages | german: required, optional oder not_required. english: required oder not_required. |
| sponsored | true bei einer bezahlten Anzeige. Nur ein Kennzeichen, die Reihenfolge ändert sich dadurch nie. |
| details | Fakten, die unser Extraktor aus der Anzeige gelesen hat: Studienfächer und -abschlüsse, Mindestsemester, Immatrikulation, Sprachniveaus, Wochenstunden, Start, Dauer, Praktikumsart, Remote-Tage, Benefits, Anschreiben, Zeugnisse, Vorerfahrung. Null, bis der aktuelle Anzeigentext gelesen wurde. |
| posted_at, first_seen_at, expires_at | posted_at (Veröffentlichung durch den Arbeitgeber, sonst first_seen_at), first_seen_at (wann wir den Job zuerst gesehen haben) und expires_at. |
Nicht enthalten: die vollständige Stellenbeschreibung und der Link zur Originalanzeige. Zeige den Job mit url und schicke Bewerber zu apply_url.
Seiten und Synchronisierung
Jobs sind nach first_seen_at sortiert, neueste zuerst. Jede Seite hat links.next, eine absolute URL zur nächsten Seite, oder null auf der letzten. Eine Gesamtzahl gibt es nicht. Um eine Kopie aktuell zu halten, frage mit since ab (letzte Abfrage minus 72 Stunden) und entferne Duplikate per id: Jobs, die wir erst prüfen, erscheinen später mit einem früheren first_seen_at. Gehe außerdem einmal am Tag die ganze Liste durch (etwa 70 Anfragen bei limit=300): So erfasst du den seltenen Job, der länger als 72 Stunden in Prüfung war, und siehst, welche Jobs geschlossen sind. Für einen einzelnen Job liefert /api/v1/jobs/{id} den Status 410, sobald er geschlossen ist.
Rate Limits
60 Anfragen pro Minute und IP. Antworten enthalten in der Regel X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (Unix-Sekunden). Über dem Limit gibt es 429 mit Retry-After: so viele Sekunden warten, dann weitermachen. Antworten aus unserem Edge-Cache können die Header einer früheren Antwort wiederholen.
Caching
Antworten werden bis zu eine Stunde gecacht, so oft kommen neue Jobs dazu. Schicke das ETag als If-None-Match zurück, um ein leeres 304 zu bekommen, wenn sich nichts geändert hat. CORS ist offen (Access-Control-Allow-Origin: *), Browser können die API also direkt aufrufen.
Fehler
Fehler kommen als JSON mit einem festen Code und einer lesbaren Meldung:
{ "error": { "code": "unknown_city", "message": "Unknown city slug: atlantis. GET /api/v1/cities lists the valid slugs." } }| Code | Status | Beschreibung |
|---|---|---|
| invalid_parameter | 400 | Ein Parameter hat ein falsches Format oder einen falschen Wert. |
| invalid_cursor | 400 | Der Cursor wurde verändert oder abgeschnitten. Nutze links.next unverändert. |
| unknown_city | 400 | Ein Stadt-Slug existiert nicht. Siehe /api/v1/cities. |
| not_found | 404 | Kein öffentlicher Job mit dieser ID. |
| method_not_allowed | 405 | Nur GET, HEAD und OPTIONS werden unterstützt. |
| gone | 410 | Der Job ist geschlossen. |
| rate_limited | 429 | Mehr als 60 Anfragen pro Minute. Warte Retry-After ab. |
| internal_error | 500 | Bei uns ist etwas schiefgelaufen. Später erneut versuchen. |
Verlinkung und ref
Verlinke jeden Job, den du zeigst, mit seiner url oder apply_url. So stimmen die Klickzahlen, die Arbeitgeber sehen, und die Anzeigen kommen weiter. Hänge ref=deineapp an deine Anfragen: Es wird an apply_url weitergegeben, zeigt uns, welche Apps Studierende schicken, und erlaubt uns, dich vor inkompatiblen Änderungen zu kontaktieren. Kein Key, keine Anmeldung.
Versionen und Changelog
Die Version steht im Pfad (/api/v1) und in meta.api_version. Nach der Beta bekommt v1 nur noch Ergänzungen: neue Felder, neue Parameter, neue Werte. Entfernungen und Umbenennungen kommen als v2, und v1 läuft danach noch 6 Monate mit Deprecation- und Sunset-Headern weiter. 17.10.2026: v1 Beta veröffentlicht.
Bedingungen
Kostenlos nutzbar, auch in kommerziellen Apps. Die Anzeigen nicht als konkurrierende Jobbörse neu veröffentlichen und das Rate Limit nicht umgehen. Die vollständigen Bedingungen stehen in Abschnitt 6 unserer Nutzungsbedingungen.
Kontakt
Du baust etwas mit der API, hast ein falsches Feld gefunden oder brauchst einen Filter, den es noch nicht gibt? Schreib an contact@workingstudentjobs.de.