curl -X POST "https://connect.jobo.world/api/auto-apply/mailboxes" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider": "imap", "address": "candidate@example.com", "imap_host": "imap.gmail.com", "password": "app-password"}'
import requests
url = "https://connect.jobo.world/api/auto-apply/mailboxes"
payload = {
"provider": "imap",
"address": "candidate@gmail.com",
"imap_host": "imap.gmail.com",
"password": "abcd efgh ijkl mnop"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
provider: 'imap',
address: 'candidate@gmail.com',
imap_host: 'imap.gmail.com',
password: 'abcd efgh ijkl mnop'
})
};
fetch('https://connect.jobo.world/api/auto-apply/mailboxes', 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/auto-apply/mailboxes",
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([
'provider' => 'imap',
'address' => 'candidate@gmail.com',
'imap_host' => 'imap.gmail.com',
'password' => 'abcd efgh ijkl mnop'
]),
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/auto-apply/mailboxes"
payload := strings.NewReader("{\n \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\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/auto-apply/mailboxes")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/auto-apply/mailboxes")
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 \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\n}"
response = http.request(request)
puts response.read_body{
"api_version": "2026-08-31",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "imap",
"address": "jsmith@example.com",
"status": "pending",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"imap_host": "<string>",
"imap_port": 123,
"imap_security": "<string>",
"username": "<string>",
"authorization_url": "<string>",
"last_error": "<string>",
"connected_at": "2023-11-07T05:31:56Z",
"last_checked_at": "2023-11-07T05:31:56Z"
}{
"error": "Invalid or expired API key",
"api_version": "2026-08-31"
}{
"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"
}{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not available in the sandbox",
"status": 404,
"code": "not_available_in_sandbox",
"detail": "Sandbox keys (jbe_test_…) serve job search, job and company lookups, Auto Apply applications, and reading mailboxes. Use a live key for every other endpoint.",
"instance": "/api/jobs/feed/managed"
}{
"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"
}{
"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": "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"
}{
"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"
}Connect a mailbox
Auto Apply is coming soon. Every mailbox endpoint needs Auto Apply enabled for the account (403 auto_apply_not_enabled otherwise), even with a sandbox key. Connecting needs a live key: a sandbox key gets 404 not_available_in_sandbox.
Optional. Connect an inbox that Jobo reads verification codes from, once per account, then pass its ID to the verification call for any application. Without a mailbox, verification steps work the same: read the code yourself and submit it through the answers call.
imap(Gmail app passwords, custom domains, most providers): Jobo checks the login during the call. You get statusconnected, or422mailbox_verification_failedwith nothing stored.outlook(Outlook and Microsoft 365, which no longer accept basic-auth IMAP): returns statuspendingand anauthorization_url. Open it, or send it to the mailbox owner, to grant consent; the mailbox then becomesconnected. Noimap_*fields apply.
Credentials are encrypted at rest and never returned. See Email verification.
curl -X POST "https://connect.jobo.world/api/auto-apply/mailboxes" \
-H "X-Api-Key: $JOBO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider": "imap", "address": "candidate@example.com", "imap_host": "imap.gmail.com", "password": "app-password"}'
import requests
url = "https://connect.jobo.world/api/auto-apply/mailboxes"
payload = {
"provider": "imap",
"address": "candidate@gmail.com",
"imap_host": "imap.gmail.com",
"password": "abcd efgh ijkl mnop"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
provider: 'imap',
address: 'candidate@gmail.com',
imap_host: 'imap.gmail.com',
password: 'abcd efgh ijkl mnop'
})
};
fetch('https://connect.jobo.world/api/auto-apply/mailboxes', 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/auto-apply/mailboxes",
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([
'provider' => 'imap',
'address' => 'candidate@gmail.com',
'imap_host' => 'imap.gmail.com',
'password' => 'abcd efgh ijkl mnop'
]),
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/auto-apply/mailboxes"
payload := strings.NewReader("{\n \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\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/auto-apply/mailboxes")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://connect.jobo.world/api/auto-apply/mailboxes")
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 \"provider\": \"imap\",\n \"address\": \"candidate@gmail.com\",\n \"imap_host\": \"imap.gmail.com\",\n \"password\": \"abcd efgh ijkl mnop\"\n}"
response = http.request(request)
puts response.read_body{
"api_version": "2026-08-31",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "imap",
"address": "jsmith@example.com",
"status": "pending",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"imap_host": "<string>",
"imap_port": 123,
"imap_security": "<string>",
"username": "<string>",
"authorization_url": "<string>",
"last_error": "<string>",
"connected_at": "2023-11-07T05:31:56Z",
"last_checked_at": "2023-11-07T05:31:56Z"
}{
"error": "Invalid or expired API key",
"api_version": "2026-08-31"
}{
"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"
}{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not available in the sandbox",
"status": 404,
"code": "not_available_in_sandbox",
"detail": "Sandbox keys (jbe_test_…) serve job search, job and company lookups, Auto Apply applications, and reading mailboxes. Use a live key for every other endpoint.",
"instance": "/api/jobs/feed/managed"
}{
"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"
}{
"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": "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"
}{
"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
Body
imap connects with a host and credentials; outlook starts the hosted Microsoft OAuth consent flow.
imap, outlook The mailbox address. Unique per account; lowercased.
Required when provider is imap. The IMAP port must be 993 or 143.
ssl, starttls Defaults to address.
Required for provider imap (use an app password where the provider offers them). Encrypted at rest, never returned.
Response
The mailbox. Status connected for a verified imap mailbox; status pending with authorization_url for an outlook mailbox awaiting consent.
Version of the Auto Apply API contract.
2026-08-31 "2026-08-31"
imap, outlook pending: anoutlookmailbox awaiting consent.connected: the last connectivity check succeeded.error: the last connectivity check failed; seelast_error.
pending, connected, error Only on a pending outlook mailbox: open this URL (or send it to the mailbox owner) to grant consent via Microsoft.

