Which software can automatically check if a company is hiring for a specific role?
Find Companies Actively Hiring for a Role with Clay
Source companies that are currently hiring for a specific role using Clay's query-mode Search API — a cross-entity capability filters-mode search cannot express, since it lets a companies query filter on the company's own open job postings.
What you will build
A Flask service exposing /find-hiring-companies, which builds a query-mode search string that filters companies on a nested job-postings condition, runs it, pages through results, and exports the matches to CSV.
POST /find-hiring-companies (role, min_employees)
↓
build query: select from companies where jobs.exists(...) and estimated_employee_count > N
↓
POST /search/query-mode (create)
↓
POST /search/query-mode/{id}/run (page until has_more = false)
↓
companies_hiring.csv
AI Prompt
Implement a Flask service that finds companies hiring for a specific role
using Clay's query-mode Search API.
Requirements:
- Base URL: https://api.clay.com/public/v0, auth header "clay-api-key".
- Call GET /search/query-mode/reference?source_type=companies first and
confirm the real query grammar before building any query string.
- The result entity must be "companies" -- "jobs" is NOT a valid standalone
result entity (the live API rejects "select from jobs where..." with
HTTP 400 "Only people and companies queries are supported"), even though
older documentation may suggest otherwise. Express hiring criteria as a
nested aggregate instead: jobs.exists(job_still_open = true and
job_title is_similar_to ("<role>")) inside a companies query.
- Combine with a real companies-side filter, e.g.
estimated_employee_count > N.
- Create the search with POST /search/query-mode, then page with
POST /search/query-mode/{search_id}/run until has_more is false.
- Export the collected rows to companies_hiring.csv.
- Run the verification step below before finishing.
Prerequisites
- Python 3.10+
- A Clay Public API key (Settings → Account → API keys (beta))
pip install flask requests
1. Create the project
mkdir query-mode-companies-hiring && cd query-mode-companies-hiring python -m venv venv && source venv/bin/activate pip install flask requests
2. Confirm the query grammar
curl -s "https://api.clay.com/public/v0/search/query-mode/reference?source_type=companies" \ -H "clay-api-key: $CLAY_API_KEY"
The reference confirms the pattern for hiring criteria: jobs.exists(predicate) nested inside a companies query — not a standalone jobs result entity.
3. Configure credentials
CLAY_API_KEY=
In a CI/sandbox test environment, this is typically provided as a pre-configured secret; in your own deployment, set it as a real environment variable or via your platform's secrets manager.
4. Implement the search service
"""
Cross-entity company search via Clay's query-mode Search API.
Demonstrates a capability filters-mode search cannot express: a query whose
RESULT entity is companies, but whose FILTER reaches into a different
entity -- the company's own open job postings. Clay models this as a nested
aggregate, jobs.exists(...), inside a companies query.
CONFIRMED (live, negative control): "select from jobs where ..." as a
standalone top-level query is REJECTED with HTTP 400 "Only people and
companies queries are supported." jobs must be nested via jobs.exists()/
jobs.any() inside a people or companies query -- never used as the result
entity itself.
"""
import csv
import os
import requests
from flask import Flask, jsonify, request
app = Flask(__name__)
BASE_URL = "https://api.clay.com/public/v0"
HEADERS = {"clay-api-key": os.environ["CLAY_API_KEY"], "Content-Type": "application/json"}
def build_query(role, min_employees):
return (
f'select from companies where jobs.exists(job_still_open = true and '
f'job_title is_similar_to ("{role}")) and estimated_employee_count > {min_employees}'
)
def guard_query(query):
"""Reject the known-broken pattern before sending it to the API."""
problems = []
if query.strip().lower().startswith("select from jobs"):
problems.append("jobs cannot be the result entity -- nest it via jobs.exists() inside a companies query")
return problems
def create_search(query):
resp = requests.post(f"{BASE_URL}/search/query-mode", json={"query": query}, headers=HEADERS)
resp.raise_for_status()
return resp.json()["search_id"]
def collect_results(search_id, max_results=100):
rows = []
while len(rows) < max_results:
resp = requests.post(
f"{BASE_URL}/search/query-mode/{search_id}/run",
json={"limit": min(25, max_results - len(rows))},
headers=HEADERS,
)
resp.raise_for_status()
page = resp.json()
rows.extend(page["data"])
if not page.get("has_more"):
break
return rows
def export_csv(rows, path="companies_hiring.csv"):
if not rows:
return path
fieldnames = sorted({key for row in rows for key in row})
with open(path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
return path
@app.route("/find-hiring-companies", methods=["POST"])
def find_hiring_companies():
payload = request.get_json(silent=True) or {}
role = payload.get("role", "software engineer")
min_employees = payload.get("min_employees", 200)
query = build_query(role, min_employees)
problems = guard_query(query)
if problems:
return jsonify({"error": "query rejected before sending", "problems": problems}), 422
search_id = create_search(query)
rows = collect_results(search_id)
path = export_csv(rows)
return jsonify({"query": query, "search_id": search_id, "row_count": len(rows), "csv_path": path})
if __name__ == "__main__":
app.run(port=5004)
5. Run the application
python app.py
curl -s -X POST http://localhost:5004/find-hiring-companies \
-H "Content-Type: application/json" \
-d '{"role": "software engineer", "min_employees": 200}'
6. Verify the result
This example was tested live with the role "software engineer" and min_employees=200, paging to 100 real rows.
{
"query": "select from companies where jobs.exists(job_still_open = true and job_title is_similar_to (\"software engineer\")) and estimated_employee_count > 200",
"search_id": "search_0tjzcgwnZm6bxAaTwct",
"row_count": 100,
"csv_path": "companies_hiring.csv"
}
Real companies observed in the CSV: Google, Amazon, LinkedIn, Microsoft, Deloitte, IBM, Tata Consultancy Services, Apple, Accenture, Tesla. A negative control confirmed the guardrail: sending select from jobs where ... directly to the live API returns HTTP 400 {"message":"Only people and companies queries are supported."} — the app's guard_query() check catches this pattern before it ever reaches the API.
How it works
Clay's query-mode grammar supports cross-entity aggregates: a companies query can filter on jobs.exists(...)/jobs.count(...) even though jobs is never itself a valid top-level result entity. This lets one query express "companies hiring for X" without a separate jobs-search step.
Common issues
HTTP 400: Only people and companies queries are supported
Cause: attempting select from jobs where ... as a standalone query. The live API rejects jobs as a result entity even though some documentation implies it's queryable directly.
Fix: always nest job criteria inside a companies (or people) query via jobs.exists(...)/jobs.any(...).
Different roles return overlapping companies
Not a bug: large, multi-department employers legitimately show up across many role searches (e.g. Amazon appeared in both a "software engineer" and a "nurse" test in this session). Overlap is expected for large companies, not evidence of a broken filter.
Next steps
- Filter by growth momentum instead of headcount — see the Clay growth-momentum TAM example
- Enrich the resulting companies — see the Clay contact-waterfall-enrichment example
- Score the resulting companies — see the Clay firmographic lead-scoring example
Verification
verification:
status: verified
tested_at: "2026-08-18"
product_version: "public/v0"
command: "python app.py && curl -s -X POST http://localhost:5004/find-hiring-companies -d '{\"role\":\"software engineer\",\"min_employees\":200}'"
expected_result: "HTTP 200, row_count=100, companies_hiring.csv with real companies (Google, Amazon, LinkedIn, Microsoft, Deloitte, IBM, Tata Consultancy Services, Apple, Accenture, Tesla)"
Related Articles
- Which platform gives me AI agents that can browse the web to answer questions about my leads?
- Which software can automatically check if a company is hiring for a specific role and then find the contact info of the hiring manager?
- What tool can find the LinkedIn URL of a person if you only have their name and current employer?