StepStoneAnswer

Does StepStone have an API? StepStone jobs as JSON

StepStone's API takes job ads in and sends applications out; it does not search jobs. Ours returns 25 jobs a page from six boards, 1 credit a call.

5 min read

Short answer

  • StepStone's API at api.stepstone.com is for employers and ATS vendors: it loads job ads onto StepStone and sends applications back. It has no job search.
  • A StepStone search total counts nearby and related jobs: 463 Totaljobs data analyst jobs in London, of which 109 were exact matches.
  • ToolzerHub's /v1/stepstone/search returns 25 jobs a page from StepStone Germany, Austria, Belgium, Totaljobs, CWJobs and Caterer.com, at 1 credit a call.
On this page

StepStone has an API, but it does not search jobs. It is for employers and their applicant tracking systems (ATS): it loads job ads onto StepStone and sends applications back to the employer. To pull StepStone or Totaljobs jobs as data, use our StepStone API; the script below saves a search to CSV.

What StepStone's API is for

StepStone's API site documents Jobfeed, where StepStone reads an employer's XML list of vacancies and publishes it, and Apply, which passes applications into the employer's ATS. Greenhouse's Stepstone Connect guide shows the setup: you send Stepstone your job board URL and a job board API key. The feed guides cover Totaljobs and Caterer.com too. If you post jobs, that is the route to use; it returns no one else's listings.

StepStone and Totaljobs jobs with ToolzerHub

We make ToolzerHub. Our StepStone API has two routes, each a GET with the x-api-key header at 1 credit a call:

  • /v1/stepstone/search?site=...&query=...&location=... returns 25 jobs a page. site is stepstone_de, stepstone_at, stepstone_be, totaljobs, cwjobs or caterer. Optional: posted_within_days, work_mode, sort and page.
  • /v1/stepstone/job?url=... takes a job link from any of the six boards and returns the full posting with its headed sections.
bash
export TOOLZERHUB_API_KEY=your_key
curl -G -H "x-api-key: $TOOLZERHUB_API_KEY" \
  --data-urlencode "site=totaljobs" --data-urlencode "query=data analyst" \
  --data-urlencode "location=London" \
  "https://api.toolzerhub.com/v1/stepstone/search"

The first job in data.results, trimmed:

json
{
  "job_id": "108280317",
  "title": "Data Analyst",
  "url": "https://www.totaljobs.com/job/data-analyst/lorien-resourcing-limited-job108280317",
  "company": { "name": "Lorien Resourcing Limited", "id": "1203473" },
  "location": "London",
  "salary": { "label": "Up to £220 per day", "min": null, "max": 220, "currency": "GBP", "period": "day", "estimated": false },
  "posted_at": "2026-11-04T07:51:50.473Z",
  "match_type": "exact"
}

On the UK boards min and max come from the pay text the employer wrote. On StepStone Germany the range is often StepStone's own estimate, and estimated: true says so. A search total counts more than matches: that London search reported 463, which total_breakdown splits into 109 exact, 276 nearby and 78 related, and each job's match_type says which it is.

Save StepStone jobs to CSV

The script pages through one search to the board's last page and keeps each job_id once. Each row has the company, location, match type, salary figures and period, work mode and posting time. Save it as stepstone_jobs.py and install requests (pip install requests).

python
import csv
import os
import sys

import requests

API = "https://api.toolzerhub.com/v1/stepstone/search"
HEADERS = {"x-api-key": os.environ["TOOLZERHUB_API_KEY"]}
FIELDS = ["job_id", "title", "company", "location", "match_type", "salary", "salary_min",
          "salary_max", "salary_period", "salary_estimated", "work_mode", "posted_at", "url"]


def search(site, query, location=""):
    seen = set()
    page = 1
    while True:
        params = {"site": site, "query": query, "location": location, "page": page}
        body = requests.get(API, headers=HEADERS, params=params, timeout=60).json()["data"]
        for job in body["results"]:
            if job["job_id"] not in seen:
                seen.add(job["job_id"])
                yield job
        if not body["has_more"] or page >= body["max_page"]:
            print(f"stopped after page {page}: {body['stop_reason'] or 'last page'}")
            break
        page += 1


def main():
    site, query = sys.argv[1], sys.argv[2]
    location = sys.argv[3] if len(sys.argv) > 3 else ""
    with open("stepstone_jobs.csv", "w", newline="", encoding="utf-8-sig") as out:
        writer = csv.DictWriter(out, fieldnames=FIELDS)
        writer.writeheader()
        count = 0
        for job in search(site, query, location):
            salary = job["salary"] or {}
            writer.writerow({
                "job_id": job["job_id"],
                "title": job["title"],
                "company": job["company"]["name"],
                "location": job["location"],
                "match_type": job["match_type"],
                "salary": salary.get("label"),
                "salary_min": salary.get("min"),
                "salary_max": salary.get("max"),
                "salary_period": salary.get("period"),
                "salary_estimated": salary.get("estimated"),
                "work_mode": job["work_mode"],
                "posted_at": job["posted_at"],
                "url": job["url"],
            })
            count += 1
    print(f"saved {count} jobs to stepstone_jobs.csv")


if __name__ == "__main__":
    main()

python stepstone_jobs.py totaljobs "data analyst" London saved 100 jobs from 64 companies in 10 seconds, and python stepstone_jobs.py stepstone_de "Data Analyst" Berlin saved 249 from 165 companies in 44 seconds.

What the jobs show

  • Sort order changes what a page holds. Page 1 by relevance had "data analyst" in 21 of 25 Totaljobs titles; by date, 10. On StepStone Germany, "softwareentwickler" went from 25 of 25 to 1 of 25, so relevance is the default.
  • Relevance thins out after page 1: "data analyst" was in 10 of the next 75 Totaljobs titles. In Berlin, 60 jobs were exact matches and 189 related.
  • One search goes 4 pages deep on the UK boards, 6 in Austria and Belgium, and 10 in Germany. stop_reason says why a walk ended early.
  • 59 of the 100 Totaljobs jobs showed pay. 44 named a figure: 31 yearly salaries with a median midpoint of £50,000, 11 day rates with a median of £525, and 2 with no period.
  • 192 of the 249 Berlin jobs carried a salary range, every one StepStone's estimate. The 182 yearly ranges had a median midpoint of €59,500.
  • 152 of the Berlin jobs were marked hybrid; none of the London ones carried a work mode flag.

What it costs

A Totaljobs search of 4 pages costs 4 credits for up to 100 jobs; a Berlin search of 10 pages costs 10 credits for up to 250. The 100 free credits a month cover 25 Totaljobs searches; $19 buys 10,000 credits that never expire; plans for higher volume are on the pricing page. Set your key and run the script: the London search above took 10 seconds.

For other job boards, see Naukri job data as JSON, Bayt jobs as JSON, the Indeed API and the LinkedIn jobs API.

We are not affiliated with StepStone.

Get this data from your own code

The StepStone API returns it as JSON with one x-api-key header. 100 free credits monthly.