BetterJobs has no native Clay app. You call it from Clay’s generic HTTP API enrichment column. Each row sends one request. The response fields you pick become new columns.
This page has two recipes:
- Is this company hiring? One company profile per row. Fixed cost: 1 credit per row.
- Which matching jobs does this company have open? A job search per row, capped at a few jobs. Up to
limitcredits per row, and 0 when nothing matches.
Recipe 1: is this company hiring?
Section titled “Recipe 1: is this company hiring?”Use this when your table has a company domain column and you want a yes / no / unknown answer per row.
-
In your Clay table, add a column and choose HTTP API as the enrichment.
-
Set the request:
Setting Value Method GETEndpoint https://api.betterjobs.cc/v1/companies/{{Domain}}Header AuthorizationBearer bj_live_...Header BetterJobs-Version2026-10-01Replace
{{Domain}}with your domain column. In Clay you insert a column reference by typing/in the field. Send the bare domain (acme-robotics.example), with nohttps://and no path. -
Run the column on two or three rows first. Open a cell to see the full JSON response.
-
Pick the response paths to add as columns:
Response path Column suggestion is_hiring.valueHiring? ( true,falseor empty = unknown)is_hiring.confidenceHiring confidence (0-1) is_hiring.basisWhy open_jobs_countOpen jobs hiring_pulse.directionTrend ( up,flat,down)top_job_families[0].job_familyTop job family -
Run the rest of the table.
Recipe 2: open jobs at this company
Section titled “Recipe 2: open jobs at this company”Use this when you want the actual job (title, apply link, date) to personalize outreach.
-
Add an HTTP API column.
-
Set the request:
Setting Value Method POSTEndpoint https://api.betterjobs.cc/v1/jobs/searchHeader AuthorizationBearer bj_live_...Header BetterJobs-Version2026-10-01Header Content-Typeapplication/json -
Paste this body and replace
{{Domain}}with your domain column:{"filters": {"company_domain_or": ["{{Domain}}"],"title_or": ["Head of RevOps", "Revenue Operations"],"posted_within_days": 30},"waterfall": {"strategy": "cheapest_first","max_credits": 3},"limit": 3}limit: 3returns at most three jobs.max_credits: 3is a hard cap on what one row can cost. Keep them equal. -
Pick the response paths to add as columns:
Response path Column suggestion data[0].titleJob title data[0].apply_urlApply link data[0].posted_atPosted (empty = unknown, use first_seen_at)data[0].first_seen_atFirst seen data[0].p_realReal-job probability (0-1) data[0].idBetterJobs job id metadata.credits_chargedCredits this row cost metadata.statuscompleteorpartialStore
data[0].id. It is stable, and fetching that job again later is free. -
Run a few rows, check
metadata.credits_charged, then run the table.
A row with no matching jobs returns data: [] and costs 0 credits. Re-running the column returns jobs you already paid for at no charge (metadata.jobs_already_paid counts them). See Credits and billing.
Build the body without typing JSON
Section titled “Build the body without typing JSON”Set the filters below and open the Clay HTTP column tab. It shows the method, endpoint, headers and body. Copy the body into Clay, then swap fixed values for {{Column}} references.
Every filter name must match the filter list. A misspelled name returns 400 unknown_filter. It is never ignored. Clay shows the error message in the cell, and error.param names the bad field.
Test the request outside Clay
Section titled “Test the request outside Clay”If a cell shows an error, run the same request from a terminal. It removes Clay from the picture.
curl https://api.betterjobs.cc/v1/jobs/search \ -H "Authorization: Bearer $BETTERJOBS_API_KEY" \ -H "BetterJobs-Version: 2026-10-01" \ -H "Content-Type: application/json" \ -d '{ "filters": { "company_domain_or": ["acme-robotics.example"], "title_or": ["Head of RevOps", "Revenue Operations"], "posted_within_days": 30 }, "waterfall": { "strategy": "cheapest_first", "max_credits": 3 }, "limit": 3 }'import osimport requests
resp = requests.post( "https://api.betterjobs.cc/v1/jobs/search", headers={ "Authorization": f"Bearer {os.environ['BETTERJOBS_API_KEY']}", "BetterJobs-Version": "2026-10-01", }, json={ "filters": { "company_domain_or": ["acme-robotics.example"], "title_or": ["Head of RevOps", "Revenue Operations"], "posted_within_days": 30, }, "waterfall": {"strategy": "cheapest_first", "max_credits": 3}, "limit": 3, }, timeout=30,)resp.raise_for_status()print(resp.json()["metadata"]["credits_charged"], "credits charged")const res = await fetch("https://api.betterjobs.cc/v1/jobs/search", { method: "POST", headers: { Authorization: `Bearer ${process.env.BETTERJOBS_API_KEY}`, "BetterJobs-Version": "2026-10-01", "Content-Type": "application/json", }, body: JSON.stringify({ filters: { company_domain_or: ["acme-robotics.example"], title_or: ["Head of RevOps", "Revenue Operations"], posted_within_days: 30, }, waterfall: { strategy: "cheapest_first", max_credits: 3 }, limit: 3, }),});if (!res.ok) throw new Error(`BetterJobs ${res.status}: ${await res.text()}`);const { metadata } = await res.json();console.log(metadata.credits_charged, "credits charged");acme-robotics.example is a fictional domain. Use one from your table.
Cost per 1,000 rows
Section titled “Cost per 1,000 rows”| Recipe | Credits per row | Worst case per 1,000 rows |
|---|---|---|
| Company profile | 1, always | 1,000 credits |
Job search, limit: 3 |
0 to 3 (0 when nothing matches) | 3,000 credits |
The worst case assumes every row returns limit new jobs. Rows with no match, duplicates merged across providers and jobs you already paid for are free, so real spend is usually lower. Enter your own numbers below. “Unique jobs” is rows × jobs returned per row.
Rate limits in Clay
Section titled “Rate limits in Clay”Clay can send many rows at once. If cells fail with 429 rate_limited, lower the column’s request rate in Clay and re-run the failed rows. Your limit per window is in GET /v1/account under rate_limit. See Rate limits.
Related
Section titled “Related”- Find companies hiring for the same searches in code.
- Field dictionary for every response path you can map.
- Troubleshooting for empty cells,
402andpartialresults.