Skip to main content

Official Python client for the Jobo Enterprise Jobs API. Access millions of job listings from 45+ ATS platforms — Greenhouse, Lever, Workday, iCIMS, SmartRecruiters, and more. Build job boards, aggregators, and recruitment tools.

Project description

Jobo

Jobo Enterprise — Python Client

Access millions of job listings from 45+ ATS platforms with a single API.
Build job boards, power job aggregators, or sync ATS data — Greenhouse, Lever, Workday, iCIMS, and more.

PyPI Python License: MIT


Why Jobo Enterprise?

  • 45+ ATS integrations — Greenhouse, Lever, Workday, iCIMS, SmartRecruiters, BambooHR, Ashby, and many more
  • Bulk feed endpoint — Cursor-based pagination to sync millions of jobs efficiently
  • Real-time search — Full-text search with location, remote, and source filters
  • Expired job sync — Keep your job board fresh by removing stale listings
  • Sync + Async — Both JoboClient and AsyncJoboClient included
  • Fully typed — Pydantic models with complete type annotations

Get your API keyenterprise.jobo.world/api-keys

Learn morejobo.world/enterprise


Installation

pip install jobo-enterprise

Quick Start

from jobo_enterprise import JoboClient

client = JoboClient(api_key="your-api-key")

# Search for software engineering jobs from Greenhouse
results = client.search_jobs(
    q="software engineer",
    location="San Francisco",
    sources="greenhouse,lever",
)

for job in results.jobs:
    print(f"{job.title} at {job.company.name}{job.listing_url}")

Authentication

Get your API key at enterprise.jobo.world/api-keys.

All requests require an API key passed via the X-Api-Key header. The client handles this automatically:

client = JoboClient(api_key="your-api-key")

Usage

Search Jobs (Simple)

Search jobs with query parameters — ideal for building job board search pages:

from jobo_enterprise import JoboClient

with JoboClient(api_key="your-api-key") as client:
    results = client.search_jobs(
        q="data scientist",
        location="New York",
        sources="greenhouse,lever",
        remote=True,
        page=1,
        page_size=50,
    )

    print(f"Found {results.total} jobs across {results.total_pages} pages")
    for job in results.jobs:
        print(f"  {job.title} at {job.company.name}{job.listing_url}")

Search Jobs (Advanced)

Use the advanced endpoint for multiple queries and locations:

results = client.search_jobs_advanced(
    queries=["machine learning engineer", "ML engineer", "AI engineer"],
    locations=["San Francisco", "New York", "Remote"],
    sources=["greenhouse", "lever", "ashby"],
    is_remote=True,
    page_size=100,
)

Auto-Paginated Search

Iterate over all matching jobs without managing pagination:

for job in client.iter_search_jobs(
    queries=["backend engineer"],
    locations=["London"],
    page_size=100,
):
    print(f"{job.title}{job.company.name}")

Bulk Jobs Feed

Fetch large batches of active jobs using cursor-based pagination — perfect for building a job aggregator or syncing to your database:

from jobo_enterprise import JoboClient, LocationFilter

with JoboClient(api_key="your-api-key") as client:
    response = client.get_jobs_feed(
        locations=[
            LocationFilter(country="US", region="California"),
            LocationFilter(country="US", city="New York"),
        ],
        sources=["greenhouse", "workday"],
        is_remote=True,
        batch_size=1000,
    )

    print(f"Got {len(response.jobs)} jobs, has_more={response.has_more}")

    # Continue with cursor
    if response.has_more:
        next_response = client.get_jobs_feed(
            cursor=response.next_cursor,
            batch_size=1000,
        )

Auto-Paginated Feed

Stream all jobs without managing cursors:

for job in client.iter_jobs_feed(batch_size=1000, sources=["greenhouse"]):
    save_to_database(job)

Expired Job IDs

Keep your job board fresh by syncing expired listings:

from datetime import datetime, timedelta

expired_since = datetime.utcnow() - timedelta(days=1)

for job_id in client.iter_expired_job_ids(expired_since=expired_since):
    mark_as_expired(job_id)

Async Support

Every method has an async equivalent via AsyncJoboClient:

import asyncio
from jobo_enterprise import AsyncJoboClient

async def main():
    async with AsyncJoboClient(api_key="your-api-key") as client:
        # Search
        results = await client.search_jobs(q="frontend developer")

        # Auto-paginated feed
        async for job in client.iter_jobs_feed(batch_size=500):
            await process_job(job)

        # Expired IDs
        async for job_id in client.iter_expired_job_ids(
            expired_since=datetime.utcnow() - timedelta(days=1)
        ):
            await mark_expired(job_id)

asyncio.run(main())

Error Handling

The client raises typed exceptions for different error scenarios:

from jobo_enterprise import (
    JoboClient,
    JoboAuthenticationError,
    JoboRateLimitError,
    JoboValidationError,
    JoboServerError,
    JoboError,
)

try:
    results = client.search_jobs(q="engineer")
except JoboAuthenticationError:
    print("Invalid API key — get one at https://enterprise.jobo.world/api-keys")
except JoboRateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except JoboValidationError as e:
    print(f"Bad request: {e.detail}")
except JoboServerError:
    print("Server error — try again later")
except JoboError as e:
    print(f"Unexpected error: {e}")

Models

All response data is returned as typed Pydantic models:

Model Description
Job A job listing with title, company, locations, compensation, etc.
JobCompany Company ID and name
JobLocation City, state, country, coordinates
JobCompensation Min/max salary, currency, period
LocationFilter Structured filter for feed endpoint
JobFeedResponse Feed response with cursor pagination
ExpiredJobIdsResponse Expired job IDs with cursor pagination
JobSearchResponse Search response with page-based pagination

Supported ATS Sources (45+)

Filter jobs by any of these applicant tracking systems:

Category Sources
Enterprise ATS workday, smartrecruiters, icims, successfactors, oraclecloud, taleo, dayforce, csod (Cornerstone), adp, ultipro, paycom
Tech & Startup greenhouse, lever_co, ashby, workable, workable_jobs, rippling, polymer, gem, pinpoint, homerun
Mid-Market bamboohr, breezy, jazzhr, recruitee, personio, jobvite, teamtailor, comeet, trakstar, zoho
SMB & Niche gohire, recooty, applicantpro, hiringthing, careerplug, hirehive, kula, careerpuck, talnet, jobscore
Specialized freshteam, isolved, joincom, eightfold, phenompeople (via eightfold)

Pass source identifiers in the sources parameter, e.g. sources=["greenhouse", "lever_co", "workday"]

Configuration

Parameter Default Description
api_key required Your Jobo Enterprise API key (get one here)
base_url https://jobs-api.jobo.world API base URL
timeout 30.0 Request timeout in seconds
httpx_client None Custom httpx.Client / httpx.AsyncClient

Use Cases

  • Build a job board — Search and display jobs from 45+ ATS platforms
  • Job aggregator — Bulk-sync millions of listings with the feed endpoint
  • ATS data pipeline — Pull jobs from Greenhouse, Lever, Workday, etc. into your data warehouse
  • Recruitment tools — Power candidate-facing job search experiences
  • Market research — Analyze hiring trends across companies and industries

Development

git clone https://github.com/Prakkie91/jobo-python.git
cd jobo-python
pip install -e ".[dev]"

# Run tests
pytest

# Lint & type check
ruff check .
mypy jobo_enterprise

Publishing to PyPI

# Install build tools
pip install build twine

# Build the package
python -m build

# Upload to PyPI
twine upload dist/*

# Push tags to GitHub
git tag v$(python -c "from jobo_enterprise import __version__; print(__version__)")
git push origin main --tags

Pushing to GitHub

# Initial setup (one-time)
git remote set-url origin https://github.com/Prakkie91/jobo-python.git

# Push
git add -A
git commit -m "release: v$(python -c 'from jobo_enterprise import __version__; print(__version__)')"
git push origin main

Links

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jobo_enterprise-1.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jobo_enterprise-1.1-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file jobo_enterprise-1.1.tar.gz.

File metadata

  • Download URL: jobo_enterprise-1.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jobo_enterprise-1.1.tar.gz
Algorithm Hash digest
SHA256 d430624d5874a0ebab95b7e0afe155be8c47d1dc067d1e6fa7c1d5bda6d4c3b4
MD5 00ebfe72c47d3c2750466098ccd5dc0b
BLAKE2b-256 dc210a0b6919a290df2865ae76602fa52454577a20abc4ee80226616ee2b760f

See more details on using hashes here.

File details

Details for the file jobo_enterprise-1.1-py3-none-any.whl.

File metadata

  • Download URL: jobo_enterprise-1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jobo_enterprise-1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5fa6b6818bfce067c3a5487a2f25a5d1a6668194bc73123f2eec2eee224502b3
MD5 6b34afcc50d500bb45491a36efcacd67
BLAKE2b-256 a3b58a2bce8a7bb10a1fc4b5924da6792de93c06cf0953bbc45dfb4e4e6d99ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page