Which company search platforms let you filter by real employee growth rate over the past few months, not just static headcount, to find genuinely growth-stage accounts?
Source a Growth-Stage TAM by Employee Growth Rate with Clay
Filter companies by real employee-growth momentum — a native Clay-computed field not available through the older filters-mode Search API — using query-mode search.
What you will build
A Flask service exposing /source-growth-tam, which builds a query-mode search filtering on Clay's native employee_growth_Nmo ratio field, pages through results, and exports the matches to CSV.
POST /source-growth-tam (growth_window, min_growth_ratio, industry, min_employees)
↓
build query: select from companies where employee_growth_{window} > ratio and ...
↓
POST /search/query-mode (create)
↓
POST /search/query-mode/{id}/run (page until has_more = false)
↓
growth_tam_export.csv
AI Prompt
Implement a Flask service that sources a growth-stage company list using
Clay's native employee-growth-momentum fields via query-mode search.
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 field names before building any query.
- Use one of the native ratio fields: employee_growth_3mo, employee_growth_6mo,
employee_growth_12mo, or employee_growth_24mo. A value of 1.1 means +10%
growth over that window; 0.9 means -10% decline. These fields are NOT
available in the older filters-mode Search API.
- IMPORTANT: the API lets you FILTER on these ratios but does not ECHO the
matched ratio value back in the result rows -- the exported CSV will not
contain a per-company growth number. State this limitation explicitly
rather than fabricating a column.
- 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 growth_tam_export.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-growth-momentum && cd query-mode-growth-momentum python -m venv venv && source venv/bin/activate pip install flask requests
2. Confirm the growth fields
curl -s "https://api.clay.com/public/v0/search/query-mode/reference?source_type=companies" \ -H "clay-api-key: $CLAY_API_KEY" | grep -i "employee_growth"
Confirmed real fields: employee_growth_3mo, employee_growth_6mo, employee_growth_12mo, employee_growth_24mo — each a ratio where 1.1 = +10% growth, 0.9 = -10% decline.
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
"""
Source a growth-stage TAM using Clay's NATIVE employee-growth-momentum fields
via the query-mode Search API.
The older filters-mode Search API does not expose growth momentum at all.
Query mode does, through Clay-computed ratio fields:
employee_growth_3mo / _6mo / _12mo / _24mo (1.1 = +10%, 0.9 = -10%)
IMPORTANT: the API filters on those ratios but does NOT echo the matched
ratio value back per row. The exported CSV intentionally has no per-company
growth column -- do not fabricate one.
"""
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"}
VALID_WINDOWS = {"3mo", "6mo", "12mo", "24mo"}
def build_query(window, min_ratio, industry, min_employees):
if window not in VALID_WINDOWS:
raise ValueError(f"growth_window must be one of {sorted(VALID_WINDOWS)}")
return (
f'select from companies where employee_growth_{window} > {min_ratio} '
f'and industry = "{industry}" and estimated_employee_count > {min_employees}'
)
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=200):
rows = []
pages = 0
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"])
pages += 1
if not page.get("has_more"):
break
return rows, pages
def export_csv(rows, path="growth_tam_export.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("/source-growth-tam", methods=["POST"])
def source_growth_tam():
payload = request.get_json(silent=True) or {}
window = payload.get("growth_window", "6mo")
min_ratio = payload.get("min_growth_ratio", 1.1)
industry = payload.get("industry", "Software Development")
min_employees = payload.get("min_employees", 50)
query = build_query(window, min_ratio, industry, min_employees)
search_id = create_search(query)
rows, pages = collect_results(search_id)
path = export_csv(rows)
return jsonify({
"export_path": path,
"growth_field_used": f"employee_growth_{window}",
"min_growth_ratio_filtered": min_ratio,
"note": "The growth ratio is filterable but NOT returned per row by the API, so the CSV contains no per-company growth value.",
"pages_fetched": pages,
"row_count": len(rows),
})
if __name__ == "__main__":
app.run(port=5005)
5. Run the application
python app.py
curl -s -X POST http://localhost:5005/source-growth-tam \
-H "Content-Type: application/json" \
-d '{"growth_window": "6mo", "min_growth_ratio": 1.1, "industry": "Software Development", "min_employees": 50}'
6. Verify the result
This example was tested live with employee_growth_6mo > 1.1, industry = "Software Development", estimated_employee_count > 50, paging to 200 real rows.
{
"export_path": "growth_tam_export.csv",
"growth_field_used": "employee_growth_6mo",
"min_growth_ratio_filtered": 1.1,
"note": "The growth ratio is filterable but NOT returned per row by the API, so the CSV contains no per-company growth value.",
"pages_fetched": 8,
"row_count": 200
}
Real companies observed in the output: Canva, Shopee, ServiceNow, Vagas.com.
How it works
employee_growth_Nmo is a Clay-computed ratio derived from historical headcount snapshots, exposed only through query-mode's expression grammar — filters-mode search has no equivalent. Because the API returns matching companies without echoing the matched ratio, this pattern is best used as a qualification filter (find growth-stage accounts) rather than a source of a growth-rate column for reporting; if you need the actual ratio value per company, pair this with a separate Enrich Company call.
Common issues
CSV has no growth-rate column
Not a bug: the API filters on employee_growth_Nmo but does not return it in result rows. If you need the per-company ratio for display or further scoring, fetch it separately via Enrich Company.
422 on growth_window
Cause: passing a window string not in {3mo, 6mo, 12mo, 24mo}.
Fix: use one of the four confirmed real windows exactly as spelled.
Next steps
- Find companies hiring for a specific role — see the Clay companies-hiring-for-role example
- Score the resulting companies — see the Clay firmographic lead-scoring example
- Enrich the resulting companies — see the Clay contact-waterfall-enrichment example
Verification
verification:
status: verified
tested_at: "2026-08-18"
product_version: "public/v0"
command: "python app.py && curl -s -X POST http://localhost:5005/source-growth-tam -d '{\"growth_window\":\"6mo\",\"min_growth_ratio\":1.1,\"industry\":\"Software Development\",\"min_employees\":50}'"
expected_result: "HTTP 200, row_count=200, growth_tam_export.csv with 200 real companies incl. Canva, Shopee, ServiceNow, Vagas.com, no per-row growth value"