Skip to main content
Jobo Enterprise provides official client libraries for three languages. Each SDK wraps the REST API with idiomatic helpers so you can skip boilerplate and focus on building.

Feature Comparison

All three SDKs share a common feature set:
FeaturePythonNode.js / TS.NET
Jobs Search
Advanced Query (AND/OR filters)
Jobs Feed (cursor-based)
Expired Jobs
Auto Apply
Geocode
Auto-pagination✅ typed iterator✅ async generatorIAsyncEnumerable
Retry with exponential backoff
Full type definitions✅ Pydantic✅ TypeScript✅ C# records
Async support✅ sync + async✅ native async✅ native async

Python

Requirements

  • Python 3.9+
  • Dependencies: httpx, pydantic

Installation

pip install jobo-enterprise

Quick Example

from jobo_enterprise import JoboClient

client = JoboClient(api_key="YOUR_API_KEY")

# Search for remote data-science jobs in the US
results = client.jobs.search(
    q="data scientist",
    location="United States",
    is_remote=True,
    page_size=10
)

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

Advanced Usage

Iterate over all matching jobs without managing page numbers. The SDK fetches the next page automatically when the current one is exhausted.
for job in client.jobs.search_iter(q="machine learning engineer"):
    print(job.title, job.company.name)
The async variant works identically:
async for job in client.jobs.async_search_iter(q="machine learning engineer"):
    print(job.title, job.company.name)
The SDK raises typed exceptions so you can handle specific failure modes.
from jobo_enterprise.exceptions import (
    JoboAuthError,
    JoboRateLimitError,
    JoboApiError,
)

try:
    results = client.jobs.search(q="engineer")
except JoboAuthError:
    print("Invalid API key — check your credentials")
except JoboRateLimitError as e:
    print(f"Rate limited — retry after {e.retry_after}s")
except JoboApiError as e:
    print(f"API error {e.status}: {e.message}")
Use AsyncJoboClient for non-blocking I/O in async frameworks like FastAPI or Django Channels.
from jobo_enterprise import AsyncJoboClient

client = AsyncJoboClient(api_key="YOUR_API_KEY")

results = await client.jobs.search(q="backend engineer", page_size=25)
for job in results.jobs:
    print(job.title)

Features

  • Pydantic models — every response is a fully-typed Pydantic model with IDE autocompletion
  • Sync + async — choose JoboClient (sync/httpx) or AsyncJoboClient (async/httpx)
  • Typed iterator paginationsearch_iter() / async_search_iter() lazily page through all results
  • Automatic retries — transient errors (429, 500, 502, 503, 504) are retried with exponential backoff

Node.js / TypeScript

Requirements

  • Node.js 18+
  • TypeScript 5+ (optional but recommended)
  • Zero runtime dependencies

Installation

npm install jobo-enterprise

Quick Example

import { JoboClient } from "jobo-enterprise";

const client = new JoboClient({ apiKey: "YOUR_API_KEY" });

// Search for remote frontend jobs
const results = await client.jobs.search({
  q: "frontend engineer",
  isRemote: true,
  pageSize: 10,
});

console.log(`Found ${results.total} jobs`);
results.jobs.forEach((job) => {
  console.log(`  ${job.title} at ${job.company.name}${job.source}`);
});

Advanced Usage

Use searchIter() to stream through every page of results automatically.
for await (const job of client.jobs.searchIter({ q: 'devops' })) {
  console.log(job.title, job.company.name);
}
You can also collect all results into an array:
const allJobs = [];
for await (const job of client.jobs.searchIter({ q: 'devops' })) {
  allJobs.push(job);
}
console.log(`Collected ${allJobs.length} jobs`);
Catch typed error classes for granular control.
import { JoboAuthError, JoboRateLimitError, JoboApiError } from 'jobo-enterprise';

try {
  const results = await client.jobs.search({ q: 'engineer' });
} catch (err) {
  if (err instanceof JoboAuthError) {
    console.error('Invalid API key');
  } else if (err instanceof JoboRateLimitError) {
    console.error(`Rate limited — retry after ${err.retryAfter}s`);
  } else if (err instanceof JoboApiError) {
    console.error(`API error ${err.status}: ${err.message}`);
  }
}
Pass a custom fetch implementation for proxies, logging, or test mocking.
import { JoboClient } from 'jobo-enterprise';

const client = new JoboClient({
  apiKey: 'YOUR_API_KEY',
  fetch: myCustomFetch,        // drop-in fetch replacement
  baseUrl: 'https://proxy.internal/jobo',  // optional base URL override
});

Features

  • Zero dependencies — uses the built-in fetch API (Node 18+)
  • Full TypeScript types — every request and response is strongly typed
  • Async generator paginationsearchIter() yields jobs across pages with for await...of
  • Automatic retries — transient errors are retried with exponential backoff and jitter

.NET

Requirements

  • .NET 6.0+ or .NET 8.0+
  • No additional dependencies beyond System.Net.Http

Installation

dotnet add package Jobo.Enterprise.Client
Or via the NuGet Package Manager:
Install-Package Jobo.Enterprise.Client

Quick Example

using Jobo.Enterprise.Client;

var client = new JoboClient("YOUR_API_KEY");

// Search for backend jobs in London
var results = await client.Jobs.SearchAsync(new SearchRequest
{
    Q = "backend engineer",
    Location = "London",
    PageSize = 10
});

Console.WriteLine($"Found {results.Total} jobs");
foreach (var job in results.Jobs)
{
    Console.WriteLine($"  {job.Title} at {job.Company.Name}{job.Source}");
}

Advanced Usage

Stream through every page of results using C#‘s native await foreach.
await foreach (var job in client.Jobs.SearchEnumerableAsync(new SearchRequest
{
    Q = "software engineer",
    IsRemote = true
}))
{
    Console.WriteLine($"{job.Title} at {job.Company.Name}");
}
This is memory-efficient — only one page is loaded at a time.
Register the client in your IServiceCollection for constructor injection.
// Program.cs or Startup.cs
builder.Services.AddJoboClient(options =>
{
    options.ApiKey = builder.Configuration["Jobo:ApiKey"];
});
Then inject it into your controllers or services:
public class JobsController : ControllerBase
{
    private readonly IJoboClient _jobo;

    public JobsController(IJoboClient jobo)
    {
        _jobo = jobo;
    }

    [HttpGet("search")]
    public async Task<IActionResult> Search([FromQuery] string q)
    {
        var results = await _jobo.Jobs.SearchAsync(new SearchRequest { Q = q });
        return Ok(results);
    }
}
Catch typed exceptions for precise error handling.
using Jobo.Enterprise.Client.Exceptions;

try
{
    var results = await client.Jobs.SearchAsync(new SearchRequest { Q = "engineer" });
}
catch (JoboAuthException)
{
    Console.WriteLine("Invalid API key");
}
catch (JoboRateLimitException ex)
{
    Console.WriteLine($"Rate limited — retry after {ex.RetryAfter}s");
}
catch (JoboApiException ex)
{
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}

Features

  • IAsyncEnumerable paginationSearchEnumerableAsync streams pages lazily with await foreach
  • ASP.NET Core DI — first-class AddJoboClient() extension for dependency injection
  • C# records & nullable annotations — every model is a record with full nullability annotations
  • Automatic retries — configurable retry policy with exponential backoff for transient HTTP errors

Shared Capabilities

All three SDKs share the same design principles and feature guarantees.

Auto-Pagination

Iterate through all results without manual page management. Each SDK uses its language’s native streaming primitive.

Retry & Backoff

Transient errors (429, 5xx) are automatically retried with exponential backoff and jitter. Configurable max retries.

Type Safety

Every request parameter and response field is fully typed — Pydantic models (Python), TypeScript interfaces (Node), C# records (.NET).

REST API (No SDK)

Don’t see your language? The REST API works with any HTTP client. Authenticate with the X-Api-Key header:
curl "https://connect.jobo.world/api/jobs?q=designer&page_size=10" \
  -H "X-Api-Key: YOUR_API_KEY"
See the Authentication page for details and the API Reference for all available endpoints.
Want an SDK for another language? Open an issue on GitHub and we’ll consider it for the roadmap.