API Reference
Job Search
Search for jobs across supported ATS platforms by title, location, and filters. Every returned job can be applied to via the Sessions endpoint.
Overview
The Job Search endpoint lets you find open positions across all supported ATS platforms. Results are pre-filtered to only include jobs that can be submitted through the API — so every job you get back is ready to be passed directly to the Sessions apply endpoint.
This is useful for clients who don't have their own job feed and want to offer end-to-end search-and-apply functionality through a single API.
Search Jobs
Search for jobs by title, location, and optional filters. Returns a list of matching jobs with full details including company information, salary data, and direct application URLs.
/jobs/search| Name | Type | Required | Description |
|---|---|---|---|
titles | string[] | Required | Array of job titles to search for (e.g. ["Software Engineer", "Frontend Developer"]) |
locations | string[] | Optional | Array of locations (e.g. ["Remote", "United States", "San Francisco, CA"]) |
postedAtMaxAgeDays | integer | Optional | Maximum age of job postings in days (default: 30) |
results | integer | Optional | Target number of results to return (default: 50, max: 500) |
excludeJobIds | string[] | Optional | Array of job IDs to exclude from results (e.g. previously applied jobs) |
filtersobjectOptional| Field | Type | Required | Description |
|---|---|---|---|
workType | string | Optional | Remote, On-site, or Hybrid |
jobType | string | Optional | full-time, part-time, contract, or internship |
experienceLevel | string | Optional | intern, junior, mid, senior, lead, or executive |
salaryMin | integer | Optional | Minimum annual salary in USD (e.g. 100000) |
companySizeMin | integer | Optional | Minimum company employee count (e.g. 50) |
curl -X POST https://apply-api.boringproject.ai/api/v1/jobs/search \
-H "Authorization: Bearer bp_live_..." \
-H "Content-Type: application/json" \
-d '{
"titles": ["Software Engineer", "Full Stack Developer"],
"locations": ["Remote", "San Francisco, CA"],
"results": 25,
"filters": {
"workType": "Remote",
"experienceLevel": "mid",
"salaryMin": 100000
}
}'{
"searchId": "srch_abc123",
"query": "Software Engineer, Full Stack Developer",
"resultsCount": 25,
"jobs": [
{
"jobId": "48291",
"title": "Senior Software Engineer",
"companyName": "Acme Corp",
"url": "https://boards.greenhouse.io/acme/jobs/48291",
"jobBoard": "Greenhouse",
"description": "We are looking for a Senior Software Engineer to join our platform team...",
"datePosted": "2024-02-10",
"location": "Remote, US",
"salary": "$140,000 - $180,000",
"salaryMin": 140000,
"salaryMax": 180000,
"salaryCurrency": "USD",
"jobType": "full-time",
"remote": true,
"seniority": "senior",
"companyDomain": "acmecorp.com",
"logoUrl": "https://logo.clearbit.com/acmecorp.com",
"companySize": 500,
"companyIndustry": "Technology"
},
...
]
}Job Object Fields
Each job in the response array contains the following fields. Fields marked Always are guaranteed to be present. Fields marked Nullable may be null when data is not available.
| Name | Type | Presence | Description |
|---|---|---|---|
jobId | string | Always | Unique job identifier |
title | string | Always | Job title |
companyName | string | Always | Hiring company name |
url | string | Always | Direct application URL — pass this as the link field in POST /sessions/apply |
jobBoard | string | Always | ATS platform name (e.g. Greenhouse, Lever, Ashby) |
description | string | null | Nullable | Full job description text (may be null if source doesn't provide it) |
datePosted | string | null | Nullable | Date the job was posted, YYYY-MM-DD (may be null) |
location | string | null | Nullable | Job location, e.g. "Remote, US" (may be null) |
remote | boolean | Always | Whether the job is remote |
salary | string | null | Nullable | Formatted salary string (e.g. "$140,000 - $180,000") |
salaryMin | number | null | Nullable | Minimum annual salary in USD |
salaryMax | number | null | Nullable | Maximum annual salary in USD |
salaryCurrency | string | null | Nullable | Salary currency code |
jobType | string | Nullable | Employment type: full-time, part-time, contract, or internship |
seniority | string | Nullable | Seniority level of the role |
companyDomain | string | Nullable | Company website domain |
logoUrl | string | null | Nullable | Company logo URL |
companySize | integer | null | Nullable | Company employee count |
companyIndustry | string | Nullable | Company industry |
Search + Apply Flow
The typical workflow is to search for jobs, let the user select which ones to apply to, and then pass them to the Sessions apply endpoint. The job url field maps directly to the link field in the apply request.
# 1. Search for jobs
curl -X POST https://apply-api.boringproject.ai/api/v1/jobs/search \
-H "Authorization: Bearer bp_live_..." \
-H "Content-Type: application/json" \
-d '{"titles": ["Software Engineer"], "locations": ["Remote"]}'
# 2. Apply to selected jobs (using job URLs from search results)
curl -X POST https://apply-api.boringproject.ai/api/v1/sessions/apply \
-H "Authorization: Bearer bp_live_..." \
-H "Content-Type: application/json" \
-d '{
"candidateProfileId": "prof_xyz789",
"jobs": [
{ "companyName": "Acme Corp", "title": "Senior Software Engineer", "jobId": "48291", "link": "https://boards.greenhouse.io/acme/jobs/48291" }
]
}'Automatic Deduplication
The API automatically excludes jobs that were returned in previous searches for your account within the last 24 hours. Each search only returns fresh, never-before-seen jobs — so you can call the search endpoint repeatedly without worrying about duplicates.
This works by tracking the job IDs returned in your recent search records (within a 24-hour rolling window). When a new search is performed, those job IDs are excluded server-side so results are always fresh.
For Autopilot Recurring sessions, deduplication is even more specific — it filters out jobs that the candidate has already applied to (regardless of success or failure), ensuring each recurring run only applies to genuinely new positions.
Filter Behavior
If fewer jobs match your filters than the requested results count, the API progressively relaxes filters to find more results. The relaxation order is: salary minimum and company size are dropped first, then experience level and job type, and finally work type and locations. This ensures you always get the most relevant results possible while still meeting your target count.
List Past Searches
Retrieve a paginated list of your previous job searches. Each record includes the search query, filters used, result count, and how many applications were submitted from that search.
/searches| Name | Type | Required | Description |
|---|---|---|---|
page | integer | Optional | Page number (default: 1) |
limit | integer | Optional | Items per page, max 100 (default: 20) |
{
"data": [
{
"searchId": "srch_abc123",
"query": "Software Engineer, Full Stack Developer",
"titles": ["Software Engineer", "Full Stack Developer"],
"locations": ["Remote", "San Francisco, CA"],
"filters": { "workType": "Remote", "experienceLevel": "mid" },
"resultsCount": 25,
"totalAvailable": 2413,
"totalCompanies": 1208,
"appliedCount": 5,
"createdAt": "2024-02-14T10:30:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 12, "totalPages": 1 }
}Get Search Record
Retrieve a specific search record by ID, including the full jobs array. Use this to show the original search results or to let users select jobs to apply to from a previous search.
/searches/:searchId{
"searchId": "srch_abc123",
"query": "Software Engineer",
"titles": ["Software Engineer"],
"locations": ["Remote"],
"filters": {},
"resultsCount": 25,
"totalAvailable": 2413,
"totalCompanies": 1208,
"appliedCount": 5,
"jobs": [
{
"jobId": "48291",
"title": "Senior Software Engineer",
"companyName": "Acme Corp",
"url": "https://boards.greenhouse.io/acme/jobs/48291",
"jobBoard": "Greenhouse",
"location": "Remote, US",
"salary": "$140,000 - $180,000",
"remote": true
}
],
"createdAt": "2024-02-14T10:30:00Z"
}Related docs
Continue reading
Sessions
Create and manage job application sessions — apply to specific jobs, run one-time searches, or set up recurring autopilot campaigns.
Candidate Profiles
Manage candidate profiles containing personal information, work experience, education, skills, languages, certifications, achievements, miscellaneous details, and resumes.
Rate Limiting
Understand API rate limits, response headers, and how to handle 429 responses gracefully with exponential backoff.