Documentation

Quick start

1. Get an API key

Self-service sign-up is not open yet. To get a key, contact us. Plans and allowances are listed on the pricing page.

Keep the key secret: it is shown to you once, and anyone holding it uses your allowance. The examples below read it from an environment variable:

TerminalCode
export JOBS_API_KEY="your-api-key"

2. Make your first request

TerminalCode
curl -i -H "X-API-Key: $JOBS_API_KEY" \ "https://api.jobs-database.de/v1/jobs?limit=2"

The response is a page of jobs:

JSONCode
{ "items": [ { "id": 536359, "title": "Technical Recruiter", "organization": "range", "url": "https://jobs.ashbyhq.com/range/25b43a09-331a-4a70-a60a-d56473b3287b", "date_posted": "2026-10-02T18:07:25.386000+00:00", "countries_derived": ["United States"], "employment_type": ["FULL_TIME"], "ai_work_arrangement": "On-site" } ], "has_more": true, "next_cursor": "NTM2MzY1" }

(Shortened — every job carries all 25 fields of the Field reference.)

The X-Jobs-Remaining response header tells you how many jobs are left in this month's allowance.

3. Page through all jobs

Keep requesting with the next_cursor of the previous page until has_more is false. Use limit=100 (the maximum) to make the fewest requests.

Python

Code
import os import time import requests BASE = "https://api.jobs-database.de" session = requests.Session() session.headers["X-API-Key"] = os.environ["JOBS_API_KEY"] def all_jobs(limit: int = 100): cursor = None while True: params = {"limit": limit} if cursor: params["cursor"] = cursor r = session.get(f"{BASE}/v1/jobs", params=params, timeout=30) if r.status_code == 429 and "Retry-After" in r.headers: time.sleep(int(r.headers["Retry-After"])) # per-minute rate limit continue r.raise_for_status() page = r.json() yield from page["items"] if not page["has_more"]: return cursor = page["next_cursor"] for job in all_jobs(): print(job["id"], job["title"], job["organization"])

JavaScript (Node.js 18+)

JavascriptCode
const BASE = "https://api.jobs-database.de"; const headers = { "X-API-Key": process.env.JOBS_API_KEY }; async function* allJobs(limit = 100) { let cursor = null; while (true) { const url = new URL("/v1/jobs", BASE); url.searchParams.set("limit", String(limit)); if (cursor) url.searchParams.set("cursor", cursor); const res = await fetch(url, { headers }); if (res.status === 429 && res.headers.has("Retry-After")) { // per-minute rate limit await new Promise((r) => setTimeout(r, Number(res.headers.get("Retry-After")) * 1000)); continue; } if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`); const page = await res.json(); yield* page.items; if (!page.has_more) return; cursor = page.next_cursor; } } for await (const job of allJobs()) { console.log(job.id, job.title, job.organization); }

A 429 without Retry-After means the monthly allowance is used up; waiting a minute will not help. See Errors & limits.

Call the API from your server or script, not from JavaScript running in a web page: the API does not send CORS headers, and a key in browser code is visible to every visitor.