Hiring.cafeAnswer

Hiring.cafe API: search its jobs as JSON

We found no public Hiring.cafe API. Ours returns 40 companies and their jobs per call at 1 credit, and a script saved 632 jobs in 5 calls.

5 min read

Short answer

  • We found no public Hiring.cafe API: /developers, /api and /docs return 404, and neither its home page nor its sitemap index links to API documentation.
  • A search call returns a page of 40 companies and their jobs, and a script saved 632 jobs in 5 calls; 375 of them came with a pay figure.
  • ToolzerHub's /v1/hiringcafe/search and /v1/hiringcafe/job return Hiring.cafe jobs as JSON with one API key, at 1 credit a call.
On this page

We found no public Hiring.cafe API or developer documentation. To get its jobs as JSON, use our Hiring.cafe API. One search call returns a page of 40 companies and their jobs, and the script below saved 632 jobs to CSV in 5 calls.

What we checked on Hiring.cafe

Hiring.cafe is a job search site that lists jobs from employers' own careers sites. When we checked, /developers, /api and /docs on its site returned a 404, and none of the 182 links on its home page or the entries in its sitemap index pointed to API documentation. Web searches turned up third-party scrapers only. A private arrangement wouldn't show up in those checks, so if you need an official feed, ask Hiring.cafe.

Hiring.cafe jobs with ToolzerHub

We make ToolzerHub. Our Hiring.cafe API reads the jobs a search on Hiring.cafe shows. It has two routes, each a GET with the x-api-key header at 1 credit a call:

  • /v1/hiringcafe/search?query=... returns one page with total, company_count and the jobs. Optional filters: location, workplace, commitment, seniority, posted_within, sort (relevance, newest, oldest, salary_high and others) and page, up to page 250.
  • /v1/hiringcafe/job?job_id_or_url=... takes a job_id or a hiringcafe.com job link and returns the description as the employer published it, pay, requirements, benefits mentioned, company facts and the link to apply on the employer's site.
bash
export TOOLZERHUB_API_KEY=your_key
curl -G -H "x-api-key: $TOOLZERHUB_API_KEY" \
  --data-urlencode "query=python developer" \
  --data-urlencode "location=Austin, TX" \
  "https://api.toolzerhub.com/v1/hiringcafe/search"

The first job in data.results, trimmed:

json
{
  "job_id": "kbzr5bitoaxy7pu7",
  "title": "Senior Python Developer",
  "company": { "name": "Charles Schwab" },
  "location": "Austin, Texas, United States",
  "workplace": "onsite",
  "commitment": ["full_time"],
  "seniority": "senior",
  "salary": { "min": 135000, "max": 162000, "currency": "USD", "period": "yearly" },
  "skills": ["Python", "Google Cloud Platform (GCP)", "Cloud Run", "Docker"],
  "posted_at": "2026-09-02T12:00:00.000Z"
}

page_size counts companies, not jobs, and each company brings up to 4 jobs.

Save Hiring.cafe jobs to CSV

The script pages through one search, keeps each job once and writes one row per job with company, place, workplace type, seniority, pay and posting time. Save it as hiringcafe_jobs.py and install requests (pip install requests). Pass - as the location to search every country.

python
import csv
import os
import sys

import requests

API = "https://api.toolzerhub.com/v1/hiringcafe/search"
HEADERS = {"x-api-key": os.environ["TOOLZERHUB_API_KEY"]}


def search(query, location=None, pages=3, sort="newest"):
    seen = set()
    for page in range(1, pages + 1):
        params = {"query": query, "sort": sort, "page": page}
        if location:
            params["location"] = location
        response = requests.get(API, headers=HEADERS, params=params, timeout=60)
        response.raise_for_status()
        body = response.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"]:
            break


def main():
    query = sys.argv[1]
    location = sys.argv[2] if len(sys.argv) > 2 and sys.argv[2] != "-" else None
    pages = int(sys.argv[3]) if len(sys.argv) > 3 else 3
    fields = ["job_id", "title", "company", "location", "workplace", "commitment",
              "seniority", "pay_min", "pay_max", "currency", "period", "posted_at",
              "apply_url"]
    with open("hiringcafe_jobs.csv", "w", newline="", encoding="utf-8") as out:
        writer = csv.DictWriter(out, fieldnames=fields)
        writer.writeheader()
        count = 0
        for job in search(query, location, pages):
            salary = job["salary"]
            writer.writerow({
                "job_id": job["job_id"],
                "title": job["title"],
                "company": job["company"]["name"],
                "location": job["location"],
                "workplace": job["workplace"],
                "commitment": "; ".join(job["commitment"]),
                "seniority": job["seniority"],
                "pay_min": salary["min"],
                "pay_max": salary["max"],
                "currency": salary["currency"],
                "period": salary["period"],
                "posted_at": job["posted_at"],
                "apply_url": job["apply_url"],
            })
            count += 1
    print(f"saved {count} jobs to hiringcafe_jobs.csv")


if __name__ == "__main__":
    main()

python hiringcafe_jobs.py "python developer" - 5 saved 632 jobs in 5 calls, and python hiringcafe_jobs.py "python developer" "Austin, TX" 5 saved 450.

What the saved pages showed

A page holds a different number of jobs each time: six saved pages held 114, 101, 115, 137, 111 and 82, with page_size 40 on every one. In the default 3-month window, "python developer" matched 127,435 jobs at 15,433 companies worldwide and 2,396 for "Austin, TX".

Pay is only what a posting lists. A job counts below as having a pay figure when salary.min or salary.max is not null.

Search, newest first, 5 calls Jobs With a pay figure Hourly or monthly
python developer, worldwide 632 375 33
python developer, Austin, TX 450 271 22

Check currency before comparing pay: of the 375 worldwide figures, 313 are yearly in USD. salary.yearly_min and yearly_max give each figure on a yearly basis.

sort changes what you get. On the first worldwide page, 80 of 114 titles sorted by relevance contain "python", against 0 of 137 sorted by newest, though Python is in the skills of all 137. The pay share differs too: 34 of 114 jobs on the relevance page, 98 of 137 on the newest page.

That first newest page is grouped by company, not strictly by date: 31 of its 40 companies hold jobs from more than one day, and its oldest job is 72 days old. These patterns come from this one search. Sort by posted_at yourself if you need strict order.

What it costs

The 632-job export took 5 credits, and a full posting is 1 more credit each. The 100 free credits a month cover 20 exports like it; $19 buys 10,000 credits that never expire, and plans for higher volume cover more searches. Set your key and the first search is a CSV in under a minute.

For other job boards, see Upwork freelance jobs and Naukri job data.

We are not affiliated with Hiring.cafe.

Get this data from your own code

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