Skip to main content

Official Python client for the Jobo Enterprise API. Access millions of job listings from 45+ ATS platforms, geocode locations, and automate job applications. Organized by feature area: Feed, Search, Locations, and Auto Apply.

Project description

Jobo

Jobo Enterprise — Python Client

Access millions of job listings, geocode locations, and automate job applications — all from a single API.

PyPI Python License: MIT


Features

Sub-client Property Description
Jobs Feed client.feed Bulk job feed with cursor-based pagination (45+ ATS)
Jobs Search client.search Full-text search with location, remote, and source filters
Locations client.locations Geocode location strings into structured coordinates
Auto Apply client.auto_apply Automate job applications with form field discovery

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)

Expired job IDs

from datetime import datetime, timedelta

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

for job_id in client.feed.iter_expired_job_ids(expired_since=expired_since):
    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.

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 — client.auto_apply

Automate job applications with form field discovery and filling.

from jobo_enterprise import FieldAnswer

# Start a session
session = client.auto_apply.start_session(job.apply_url)

print(f"Provider: {session.provider_display_name}")
print(f"Fields: {len(session.fields)}")

# Fill in fields — `type` mirrors the FormFieldInfo.type of each field
answers = [
    FieldAnswer(field_id="first_name", type="text", value="John"),
    FieldAnswer(field_id="last_name", type="text", value="Doe"),
    FieldAnswer(field_id="email", type="text", value="john@example.com"),
]

result = client.auto_apply.set_answers(session.session_id, answers)

if result.is_terminal:
    print("Application submitted!")

# Clean up
client.auto_apply.end_session(session.session_id)

Profiles & one-shot run

from jobo_enterprise import AutoApplyProfileRequest

profile = client.auto_apply.create_profile(
    AutoApplyProfileRequest(
        name="Default",
        first_name="John",
        last_name="Doe",
        email="john@example.com",
        phone="+1-555-0100",
    )
)

# Run the full flow end-to-end against the stored profile
run = client.auto_apply.run(profile.id, job.apply_url)
print(run.status, run.steps_completed, run.fields_filled)

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

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

try:
    results = client.search.search(q="engineer")
except JoboAuthenticationError:
    print("Invalid API key")
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")

Supported ATS Sources (45+)

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

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)
httpx_client None Custom httpx client

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
  • Auto-apply automation — Automate job applications at scale
  • Location intelligence — Geocode and normalize job locations

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-3.0.0.tar.gz (24.4 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-3.0.0-py3-none-any.whl (22.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for jobo_enterprise-3.0.0.tar.gz
Algorithm Hash digest
SHA256 c961e7c5fee8697e1a67d100bc3abdcf8f1bdbca12f24157823a77ba84c26b58
MD5 54bd7f4cb03fe4b793da79ab971cea4c
BLAKE2b-256 d1ac82b3f4e57fbf80d8ac2eb4e8a073d623d19e4365409e6fc9ce6cb2981a97

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for jobo_enterprise-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 09bc662b8103e063d2daea3f8dd5488b81a6faf4da312249118b545792df617e
MD5 84b731f600d265812fc89be0dcb86e94
BLAKE2b-256 b7b051359be737d1fec3758c0c4ead12629ce3e662772f126630aca716ad03b4

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