curl -G "https://connect.jobo.world/api/jobs" \
-H "X-Api-Key: $JOBO_API_KEY" \
--data-urlencode "q=software engineer" \
--data-urlencode "work_model=remote" \
--data-urlencode "page_size=25"import os
from jobo_enterprise import JoboClient
with JoboClient(api_key=os.environ["JOBO_API_KEY"]) as client:
results = client.search.search(
q="software engineer",
work_model="remote",
page_size=25,
)
print(results.total)
for job in results.jobs:
print(job.title, job.company.name)
const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://connect.jobo.world/api/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://connect.jobo.world/api/jobs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://connect.jobo.world/api/jobs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://connect.jobo.world/api/jobs")
.header("X-Api-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Api-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"jobs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"normalized_title": "<string>",
"occupation": {
"id": "esco:8d3e8aaa-791b-4c75-a465-f3f827028f50",
"name": "Registered Nurse",
"category": "Healthcare",
"subcategory": "Nursing",
"isco_code": "2221",
"onet_soc_codes": [
"29-1141.00"
]
},
"company": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"website": "<string>",
"logo_url": "<string>",
"summary": "<string>",
"industries": [
"<string>"
],
"categories": [
"<string>"
],
"linkedin_url": "<string>",
"crunchbase_url": "<string>",
"details_url": "<string>"
},
"description": "<string>",
"language": "en",
"summary": "<string>",
"listing_url": "<string>",
"apply_url": "<string>",
"locations": [
{
"location": "<string>",
"city": "<string>",
"region": "<string>",
"country": "<string>",
"latitude": 123,
"longitude": 123
}
],
"compensation": {
"min": 123,
"max": 123,
"currency": "<string>",
"period": "hourly"
},
"employment_type": "Full-time",
"workplace_type": "Remote",
"experience_level": "Intern",
"source": "greenhouse",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"date_posted": "2023-11-07T05:31:56Z",
"valid_through": "2023-11-07T05:31:56Z",
"qualifications": {
"must_have": {
"education": [
"<string>"
],
"certifications": [
"<string>"
],
"skills": [
{
"name": "<string>",
"type": "hard"
}
]
},
"preferred": {
"education": [
"<string>"
],
"certifications": [
"<string>"
],
"skills": [
{
"name": "<string>",
"type": "hard"
}
]
}
},
"responsibilities": [
"<string>"
],
"benefits": [
"<string>"
],
"is_work_auth_required": true,
"is_h1b_sponsor": true,
"is_clearance_required": true,
"external_id": "000123"
}
],
"total": 123,
"page": 123,
"page_size": 123,
"total_pages": 123,
"facets": {},
"warnings": [
{
"code": "companies_unmatched",
"field": "companies.include",
"message": "<string>"
}
],
"filters": {
"companies": {
"matched": [
{
"query": "<string>",
"companies": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"provider_id": "workday",
"website": "<string>",
"is_enabled": true
}
]
}
],
"unmatched": [
"<string>"
],
"exclude_unmatched": [
"<string>"
]
}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"docs_url": "https://jobo.world/docs/guides/sync-a-database",
"api_version": "2026-08-31"
}{
"error": "Invalid or expired API key",
"api_version": "2026-08-31"
}{
"error": "Insufficient credits",
"detail": "This request needs 75 credits ($0.075). Your wallet balance is 12 credits ($0.012). Top up your wallet to continue.",
"group": "JobSearch",
"credits_required": 123,
"credits_balance": 123,
"cost_per_request_usd": 0.075,
"quota_remaining": 123
}{
"error": "Rate limit exceeded",
"detail": "Per-minute JobSearch request limit of 180 exceeded. Try again shortly.",
"retry_after_seconds": 1,
"code": "rate_limit_exceeded",
"group": "JobSearch",
"api_version": "2026-08-31"
}{
"message": "An error occurred",
"detail": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"docs_url": "https://jobo.world/docs/guides/sync-a-database",
"api_version": "2026-08-31"
}List jobs
Search active jobs with query-string filters. Filters take lowercase canonical keys (full-time), not the display values jobs return (Full-time); see Enums. For several queries or locations, or include/exclude filters, use POST /api/jobs/search.
Billed per delivered job: included jobs first, then the wallet. The Unlimited plan does not cover Search. See Billing.
curl -G "https://connect.jobo.world/api/jobs" \
-H "X-Api-Key: $JOBO_API_KEY" \
--data-urlencode "q=software engineer" \
--data-urlencode "work_model=remote" \
--data-urlencode "page_size=25"import os
from jobo_enterprise import JoboClient
with JoboClient(api_key=os.environ["JOBO_API_KEY"]) as client:
results = client.search.search(
q="software engineer",
work_model="remote",
page_size=25,
)
print(results.total)
for job in results.jobs:
print(job.title, job.company.name)
const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://connect.jobo.world/api/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://connect.jobo.world/api/jobs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://connect.jobo.world/api/jobs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://connect.jobo.world/api/jobs")
.header("X-Api-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Api-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"jobs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"normalized_title": "<string>",
"occupation": {
"id": "esco:8d3e8aaa-791b-4c75-a465-f3f827028f50",
"name": "Registered Nurse",
"category": "Healthcare",
"subcategory": "Nursing",
"isco_code": "2221",
"onet_soc_codes": [
"29-1141.00"
]
},
"company": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"website": "<string>",
"logo_url": "<string>",
"summary": "<string>",
"industries": [
"<string>"
],
"categories": [
"<string>"
],
"linkedin_url": "<string>",
"crunchbase_url": "<string>",
"details_url": "<string>"
},
"description": "<string>",
"language": "en",
"summary": "<string>",
"listing_url": "<string>",
"apply_url": "<string>",
"locations": [
{
"location": "<string>",
"city": "<string>",
"region": "<string>",
"country": "<string>",
"latitude": 123,
"longitude": 123
}
],
"compensation": {
"min": 123,
"max": 123,
"currency": "<string>",
"period": "hourly"
},
"employment_type": "Full-time",
"workplace_type": "Remote",
"experience_level": "Intern",
"source": "greenhouse",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"date_posted": "2023-11-07T05:31:56Z",
"valid_through": "2023-11-07T05:31:56Z",
"qualifications": {
"must_have": {
"education": [
"<string>"
],
"certifications": [
"<string>"
],
"skills": [
{
"name": "<string>",
"type": "hard"
}
]
},
"preferred": {
"education": [
"<string>"
],
"certifications": [
"<string>"
],
"skills": [
{
"name": "<string>",
"type": "hard"
}
]
}
},
"responsibilities": [
"<string>"
],
"benefits": [
"<string>"
],
"is_work_auth_required": true,
"is_h1b_sponsor": true,
"is_clearance_required": true,
"external_id": "000123"
}
],
"total": 123,
"page": 123,
"page_size": 123,
"total_pages": 123,
"facets": {},
"warnings": [
{
"code": "companies_unmatched",
"field": "companies.include",
"message": "<string>"
}
],
"filters": {
"companies": {
"matched": [
{
"query": "<string>",
"companies": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"provider_id": "workday",
"website": "<string>",
"is_enabled": true
}
]
}
],
"unmatched": [
"<string>"
],
"exclude_unmatched": [
"<string>"
]
}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"docs_url": "https://jobo.world/docs/guides/sync-a-database",
"api_version": "2026-08-31"
}{
"error": "Invalid or expired API key",
"api_version": "2026-08-31"
}{
"error": "Insufficient credits",
"detail": "This request needs 75 credits ($0.075). Your wallet balance is 12 credits ($0.012). Top up your wallet to continue.",
"group": "JobSearch",
"credits_required": 123,
"credits_balance": 123,
"cost_per_request_usd": 0.075,
"quota_remaining": 123
}{
"error": "Rate limit exceeded",
"detail": "Per-minute JobSearch request limit of 180 exceeded. Try again shortly.",
"retry_after_seconds": 1,
"code": "rate_limit_exceeded",
"group": "JobSearch",
"api_version": "2026-08-31"
}{
"message": "An error occurred",
"detail": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"docs_url": "https://jobo.world/docs/guides/sync-a-database",
"api_version": "2026-08-31"
}Authorizations
Query Parameters
Free-text search query. By default it matches broadly against the job title, company name, popular skills, and summary with typo tolerance. Wrap the value in double quotes (e.g. q="Quantitative Developer") for an exact, contiguous phrase match restricted to the job title only.
When true, search title, alternative titles, company, popular skills, and summary. When false, restrict matching to titles and curated alternative titles. A double-quoted query always matches an exact contiguous phrase in the literal title.
Location filter (city, region, or country)
Comma-separated work models (remote, hybrid, onsite)
Comma-separated employment types (full-time, part-time, contract, internship, freelance, temporary)
Comma-separated experience levels. Canonical values: intern, entry, mid, senior, lead, executive.
Comma-separated ISO 639-1 codes of the description language (e.g. en,de).
Only return jobs whose employer posting date is on or after this date
Only return jobs whose employer posting date is on or before this date
Minimum annual salary in USD
x >= 0Maximum annual salary in USD
x >= 0Comma-separated skill names
Comma-separated company-industry names. A job matches any supplied value.
Comma-separated company business-model categories (b2b, b2c, b2b2c, saas, marketplace, service-provider). A job matches any supplied value.
Comma-separated occupation categories (the job's occupation.category, e.g. Healthcare). A job matches any supplied value. Exact match, ignoring case. GET /api/occupations lists every value. Jobs without an occupation never match.
Comma-separated occupation subcategories (the job's occupation.subcategory, e.g. Nursing). A job matches any supplied value. Exact match, ignoring case. GET /api/occupations lists every value. Four subcategory names contain a comma (e.g. Film, TV & Stage Production) and are split here, so they match nothing; filter those with POST /api/jobs/search.
Comma-separated occupation ids (the job's occupation.id, e.g. esco:8d3e8aaa-791b-4c75-a465-f3f827028f50). A job matches any supplied value. Use ids, not names: names can improve between taxonomy releases, ids don't. GET /api/occupations lists every id. To exclude categories, subcategories or occupations, use POST /api/jobs/search.
Only return jobs first indexed on or after this UTC timestamp
Only return jobs first indexed on or before this UTC timestamp
Result order. relevance (default) ranks by match quality, or by most recently updated without q; it shifts as jobs update, so paging can skip or repeat a job. discovered_asc and discovered_desc order by created_at (first indexed), which never changes: pair them with a discovered_after / discovered_before window for stable pages. See Pagination.
relevance, discovered_asc, discovered_desc Page number (1-indexed)
x >= 1Number of results per page (max 100)
1 <= x <= 100Format of each job's description. markdown (default) returns it as stored. html renders it to HTML on the fly: raw HTML in the source is escaped and only http(s), mailto and relative URLs are kept.
markdown, html Comma-separated heavy fields to return: description, summary, qualifications, responsibilities, benefits. Core fields (id, title, company, locations, compensation, dates, …) always come back.
Omit it for the full job (the default), pass a subset to keep only those heavy fields, or pass an empty value (?include_fields=) for core fields only. Names are case-insensitive; unknown names are ignored. An excluded description is "", summary is null, qualifications has empty buckets, and responsibilities and benefits are [].
Comma-separated facets to compute: work_model, experience_level, employment_type, sources, industries, skills, countries, company_categories, job_categories, job_subcategories, occupations. Omit it for work_model, experience_level, employment_type and sources; pass an empty value for none. Occupation facet buckets carry name and parent, so you can nest category › subcategory › occupation.
Response
Paginated list of matching jobs
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Non-fatal problems with the request. Omitted when there is nothing to report. The same codes are sent, comma-separated, in the X-Jobo-Warnings response header, so a client can branch without parsing the body.
Show child attributes
Show child attributes
How the server interpreted the filters that needed resolving. Present only when a companies filter was supplied.
Show child attributes
Show child attributes

