# First request carries the filters and batch size.
curl -X POST "https://connect.jobo.world/api/jobs/feed" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sources": ["greenhouse"], "batch_size": 1000}'
# Continuation requests carry ONLY the cursor.
curl -X POST "https://connect.jobo.world/api/jobs/feed" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cursor": "eyJ2IjoxLCJ..."}'from jobo_enterprise import JoboClient
with JoboClient(api_key="YOUR_API_KEY") as client:
# iter_jobs walks the cursor for you.
for job in client.feed.iter_jobs(sources=["greenhouse"], batch_size=1000):
save_to_database(job)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
locations: [{country: '<string>', region: '<string>', city: '<string>'}],
sources: ['<string>'],
work_models: [],
posted_after: '2023-11-07T05:31:56Z',
updated_after: '2023-11-07T05:31:56Z',
stable_scan: true,
cursor: '<string>',
batch_size: 1000
})
};
fetch('https://connect.jobo.world/api/jobs/feed', 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/feed",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'locations' => [
[
'country' => '<string>',
'region' => '<string>',
'city' => '<string>'
]
],
'sources' => [
'<string>'
],
'work_models' => [
],
'posted_after' => '2023-11-07T05:31:56Z',
'updated_after' => '2023-11-07T05:31:56Z',
'stable_scan' => true,
'cursor' => '<string>',
'batch_size' => 1000
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://connect.jobo.world/api/jobs/feed"
payload := strings.NewReader("{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://connect.jobo.world/api/jobs/feed")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/jobs/feed")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}"
response = http.request(request)
puts response.read_body{
"jobs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"normalized_title": "<string>",
"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>",
"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>"
},
"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
}
],
"next_cursor": "<string>",
"has_more": true
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}Stream the job feed
Export active jobs in batches of up to 1,000. Omit cursor on the first
request, then pass only the returned next_cursor — the cursor embeds the
initial filters and batch size, and values sent alongside a cursor are
ignored. Persist the cursor so an interrupted scan can resume, and
paginate serially (one in-flight request per cursor).
New scans default to stable_scan: true: pages follow immutable creation
time, so mid-scan updates or deletions cannot shift records across page
boundaries. Set stable_scan: false explicitly for the legacy
update-recency ordering. Use updated_after for incremental additions
and edits after the backfill.
Retry only 503 (honoring Retry-After) and 429, with bounded
backoff. A 400 for a malformed cursor, or a 409 with code
feed_cursor_restart_required, means discard the cursor and restart
the scan with stable_scan: true. Configure clients with a response
timeout of at least 120 seconds.
# First request carries the filters and batch size.
curl -X POST "https://connect.jobo.world/api/jobs/feed" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sources": ["greenhouse"], "batch_size": 1000}'
# Continuation requests carry ONLY the cursor.
curl -X POST "https://connect.jobo.world/api/jobs/feed" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cursor": "eyJ2IjoxLCJ..."}'from jobo_enterprise import JoboClient
with JoboClient(api_key="YOUR_API_KEY") as client:
# iter_jobs walks the cursor for you.
for job in client.feed.iter_jobs(sources=["greenhouse"], batch_size=1000):
save_to_database(job)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
locations: [{country: '<string>', region: '<string>', city: '<string>'}],
sources: ['<string>'],
work_models: [],
posted_after: '2023-11-07T05:31:56Z',
updated_after: '2023-11-07T05:31:56Z',
stable_scan: true,
cursor: '<string>',
batch_size: 1000
})
};
fetch('https://connect.jobo.world/api/jobs/feed', 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/feed",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'locations' => [
[
'country' => '<string>',
'region' => '<string>',
'city' => '<string>'
]
],
'sources' => [
'<string>'
],
'work_models' => [
],
'posted_after' => '2023-11-07T05:31:56Z',
'updated_after' => '2023-11-07T05:31:56Z',
'stable_scan' => true,
'cursor' => '<string>',
'batch_size' => 1000
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://connect.jobo.world/api/jobs/feed"
payload := strings.NewReader("{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://connect.jobo.world/api/jobs/feed")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/jobs/feed")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"locations\": [\n {\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\"\n }\n ],\n \"sources\": [\n \"<string>\"\n ],\n \"work_models\": [],\n \"posted_after\": \"2023-11-07T05:31:56Z\",\n \"updated_after\": \"2023-11-07T05:31:56Z\",\n \"stable_scan\": true,\n \"cursor\": \"<string>\",\n \"batch_size\": 1000\n}"
response = http.request(request)
puts response.read_body{
"jobs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"normalized_title": "<string>",
"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>",
"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>"
},
"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
}
],
"next_cursor": "<string>",
"has_more": true
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"code": "<string>",
"api_version": "2026-07-21"
}Authorizations
API key provided by Jobo
Body
Cursor-paginated export request. The cursor preserves the filters and batch size from the first request; start a new scan to change them.
Show child attributes
Show child attributes
Filter by work model: remote, hybrid, onsite. null = all jobs
remote, hybrid, onsite Return jobs whose employer posting time or first-indexed time is on
or after this UTC timestamp. Use updated_after when edits matter.
Return jobs created or updated on or after this UTC timestamp.
Page by immutable creation time rather than update recency (default). Stable scans cannot skip or duplicate records when jobs are updated or deleted mid-scan. Set false explicitly for the legacy update-recency ordering.
Opaque cursor from next_cursor. Omit on the first request.
1 <= x <= 1000
