Skip to main content
Jobo

Jobo Enterprise — Python Client

Access millions of job listings, enriched company profiles, and geocoding — all from a single API.

PyPI Python License: MIT


Features

Sub-client Property Description
Jobs Feed client.feed Bulk and managed job feeds with cursor-based pagination (106 ATS)
Jobs Search client.search Full-text search, filters, facets, and single-job lookup
Companies client.companies Enriched company profiles and per-company job listings
Locations client.locations Geocode location strings into structured coordinates

Both sync (JoboClient) and async (AsyncJoboClient) are included.

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


Installation

pip install jobo-enterprise

Quick Start

from jobo_enterprise import JoboClient

with JoboClient(api_key="your-api-key") as client:
    # Search for jobs
    results = client.search.search(q="software engineer", location="San Francisco")
    for job in results.jobs:
        print(f"{job.title} at {job.company.name}")

    # Geocode a location
    geo = client.locations.geocode("London, UK")
    print(f"{geo.locations[0].display_name}: {geo.locations[0].latitude}, {geo.locations[0].longitude}")

Authentication

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

Jobs Feed — client.feed

Bulk-sync millions of active jobs using cursor-based pagination.

Fetch a batch

from jobo_enterprise import LocationFilter

response = client.feed.get_jobs(
    locations=[
        LocationFilter(country="US", region="California"),
        LocationFilter(country="US", city="New York"),
    ],
    sources=["greenhouse", "workday"],
    work_models=["remote", "hybrid"],
    batch_size=1000,
)

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

Auto-paginate all jobs

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

Incremental sync

After the initial backfill, pass updated_after to pick up only what changed. Scans page by immutable creation time by default (stable_scan), so records cannot shift across page boundaries while you are reading.

from datetime import datetime, timedelta, timezone

since = datetime.now(timezone.utc) - timedelta(hours=1)

for job in client.feed.iter_jobs(updated_after=since, batch_size=1000):
    upsert(job)

Managed feed

Jobs from the companies you configured through Managed Job Scraping in the Jobo portal. Same batch and cursor semantics, minus the locations filter.

for job in client.feed.iter_managed_jobs(batch_size=1000):
    save_to_database(job)

Expired job IDs

expired_since is optional and defaults to 24 hours ago. Maximum lookback is 7 days.

for job_id in client.feed.iter_expired_job_ids():
    mark_as_expired(job_id)

Jobs Search — client.search

Full-text search with filters and page-based pagination.

Simple search

from jobo_enterprise import WorkModel

results = client.search.search(
    q="data scientist",
    location="New York",
    sources="greenhouse,lever",
    work_model=WorkModel.REMOTE,  # or just "remote"
    min_salary_usd=120000,
    page_size=50,
)

print(f"Found {results.total} jobs across {results.total_pages} pages")

Closed value sets. Parameters with a fixed set of accepted values ship as enums for discoverability — WorkModel, EmploymentType, ExperienceLevel, CompensationPeriod, and SkillType. Each member subclasses str, so passing the equivalent literal (e.g. "remote") is always valid too. Values are lowercase and hyphenated ("full-time", "per-diem"); the API matches them exactly, so a misspelt value simply matches nothing.

Fetch one job

job = client.search.get_job("a1b2c3d4-e5f6-7890-abcd-ef1234567890")

Unmetered — this endpoint deducts no credits, which makes it a cheap way to wire up an integration.

Trim the payload

Omit include_fields for the whole job, pass a subset to keep only those heavy fields, or pass an empty value for core fields only.

results = client.search.search(q="data scientist", include_fields="summary", page_size=50)

Advanced search (typed filters & facets)

from jobo_enterprise import InclusionExclusionFilter, RangeFilter

results = client.search.search_advanced(
    queries=["machine learning engineer", "ML engineer", "AI engineer"],
    locations=["San Francisco", "New York"],
    sources=["greenhouse", "lever", "ashby"],
    work_models=["remote", "hybrid"],
    skills=InclusionExclusionFilter(include=["python"], exclude=["php"]),
    salary_usd=RangeFilter(min=150000),
    include_facets=["work_model", "experience_level"],
    page_size=100,
)

for facet, buckets in results.facets.items():
    print(facet, [(b.key, b.count) for b in buckets])

Auto-paginate all results

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

Companies — client.companies

Fetch fully enriched company profiles and list jobs scoped to a company.

company = client.companies.get(job.company.id)
print(company.name, company.website, company.industries)

# Jobs for a single company (paginated)
jobs = client.companies.get_jobs(job.company.id, page_size=50)
print(f"{jobs.total} jobs at {company.name}")

Locations — client.locations

Geocode location strings into structured data with coordinates.

result = client.locations.geocode("San Francisco, CA")

for location in result.locations:
    print(f"{location.display_name}: {location.latitude}, {location.longitude}")

Auto Apply

Not covered by this client. The Auto Apply contract is profileless and callback-driven, and application creation is not yet open to traffic. Call it over plain HTTPS — see the Auto Apply reference.


Async Support

Every sub-client 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.search(q="frontend developer")

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

        # Geocode
        geo = await client.locations.geocode("Berlin, DE")

asyncio.run(main())

Error Handling

429 and 503 are retried for you with bounded backoff, honouring Retry-After. Everything else raises immediately, as a subclass of JoboError:

from jobo_enterprise import (
    JoboAuthenticationError,
    JoboPermissionError,
    JoboNotFoundError,
    JoboRateLimitError,
    JoboValidationError,
    JoboCursorRestartRequiredError,
    JoboServerError,
    JoboError,
)

try:
    results = client.search.search(q="engineer")
except JoboAuthenticationError:
    print("Invalid API key")
except JoboPermissionError:
    print("Key is not entitled to this resource")
except JoboNotFoundError:
    print("No such job or company")
except JoboRateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except JoboValidationError as e:
    print(f"Bad request: {e.detail} ({e.code})")
except JoboCursorRestartRequiredError:
    print("Feed cursor is spent — discard it and start a new scan")
except JoboServerError:
    print("Server error — try again later")

Every exception carries the API's machine-readable problem code when one is supplied, alongside status_code, detail, and the raw response_body.

Supported ATS Sources (106)

Category Sources
Enterprise ATS workday, smartrecruiters, icims, successfactors, oraclecloud, taleo, dayforce, csod, 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

The full catalogue of 106 providers is listed in the API documentation. Treat it as an open set — new provider_id values appear as platforms are added.

Configuration

Parameter Default Description
api_key required Your API key
base_url https://connect.jobo.world API base URL
timeout 30.0 Request timeout (seconds)
feed_timeout 120.0 Response timeout for the feed routes
httpx_client None Custom httpx client

Use Cases

  • Build a job board — Search and display jobs from 106 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
  • Company intelligence — Enrich listings with funding, headcount, and tech-stack data
  • Location intelligence — Geocode and normalize job locations

Links

License

MIT — see LICENSE.

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-4.0.0.tar.gz (28.0 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-4.0.0-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for jobo_enterprise-4.0.0.tar.gz
Algorithm Hash digest
SHA256 e04939e7ba19544ad2f24e8abdca9ebaa5248579edcc3e1df3dcdc7253126666
MD5 8366c09715267138fb7954c3774af441
BLAKE2b-256 5ce4af58e0d6500cc1ac78b7389c1cb9e461f604c7cd0b6169b6442241d7e6f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for jobo_enterprise-4.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ec69050f689c21cbbdec13c6a87a84c31d5670fb3855651e1864551811d4a7b
MD5 dad9fe14269868191926e8e50e6a6535
BLAKE2b-256 69e39e497efced8eb7a809dc4a8a91d4e3ea82319c31939555fe474ed9c77428

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 files

3.0.0

2 files

1.1.1

2 files

1.1

2 files

1.0.1

2 files

Supported by

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