Is there software that can automatically enrich a lead with the latest annual revenue of their company?
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
Qualify Companies by Exact Annual Revenue with Clay
Get an exact annual revenue figure per company domain and qualify it against an ICP revenue band — using Clay's Company Revenue (Exact) waterfall function, which cross-checks multiple data providers for accuracy.
What you will build
A Flask service exposing /qualify-by-revenue, which submits company domains to Clay's real revenue-lookup routine and buckets each into qualified, disqualified, or unknown based on a revenue range.
POST /qualify-by-revenue (domains, min_revenue, max_revenue)
↓
POST /routines/{routine_id}/run (Company Revenue (Exact))
↓
GET /routines/run/{run_id}/results (poll until complete)
↓
{ qualified, disqualified, unknown }
AI Prompt
Implement a Flask service that qualifies companies by exact annual revenue
using Clay's "Company Revenue (Exact)" managed function.
Requirements:
- Base URL: https://api.clay.com/public/v0, auth header "clay-api-key".
- Find the real routine id via your workspace's routine catalog.
- Confirmed real input schema: {"Company Domain": hostname} (required).
- Confirmed real result key: "Company Revenue" -- a STRING of digits (e.g.
"100000000"). Parse it to an integer before comparing against a range.
- If revenue is absent or the parse fails, put the domain in "unknown" --
never treat an unparseable/missing value as automatically disqualified.
- 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 company-exact-revenue && cd company-exact-revenue python -m venv venv && source venv/bin/activate pip install flask requests
2. Discover the routine and its real schema
clay routines list | grep -A2 '"Company Revenue (Exact)"'
clay routines get function:t_XXXXXXXXXXXXXXXXXXXX
3. Configure credentials
CLAY_API_KEY= CLAY_ROUTINE_ID_REVENUE=function:t_XXXXXXXXXXXXXXXXXXXX
In a CI/sandbox test environment, CLAY_API_KEY and CLAY_ROUTINE_ID_REVENUE are typically provided as pre-configured secrets; in your own deployment, set them as real environment variables or via your platform's secrets manager.
4. Implement the revenue-qualification service
"""
Revenue-qualification service backed by the Clay 'Company Revenue (Exact)'
waterfall routine.
CONFIRMED (live): the result key 'Company Revenue' is a STRING of digits,
not a number -- parse it before comparing. Absent/unparseable revenue goes
to 'unknown', never 'disqualified'.
"""
import os
import time
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"}
ROUTINE_ID = os.environ["CLAY_ROUTINE_ID_REVENUE"]
POLL_INTERVAL = int(os.environ.get("POLL_INTERVAL_SECONDS", 5))
MAX_WAIT = int(os.environ.get("MAX_WAIT_SECONDS", 180))
def submit(domains):
items = [{"id": d, "inputs": {"Company Domain": d}} for d in domains]
resp = requests.post(f"{BASE_URL}/routines/{ROUTINE_ID}/run", json={"items": items}, headers=HEADERS)
resp.raise_for_status()
return resp.json()["routine_run_id"]
def poll(run_id):
deadline = time.time() + MAX_WAIT
while time.time() < deadline:
resp = requests.get(f"{BASE_URL}/routines/run/{run_id}/results", headers=HEADERS)
resp.raise_for_status()
body = resp.json()
if body["status"] == "complete":
return body.get("data", [])
time.sleep(POLL_INTERVAL)
raise TimeoutError(f"Routine run {run_id} did not complete within {MAX_WAIT}s")
def parse_revenue(result):
raw = (result or {}).get("Company Revenue")
if raw is None:
return None
try:
return int(raw)
except (TypeError, ValueError):
return None
@app.route("/qualify-by-revenue", methods=["POST"])
def qualify_by_revenue():
payload = request.get_json(silent=True) or {}
domains = payload.get("domains", [])
min_revenue = payload.get("min_revenue", 0)
max_revenue = payload.get("max_revenue", float("inf"))
run_id = submit(domains)
items = poll(run_id)
qualified, below_threshold, unknown = [], [], []
for item in items:
revenue = parse_revenue(item.get("result"))
if revenue is None:
unknown.append(item["id"])
elif min_revenue <= revenue <= max_revenue:
qualified.append({"domain": item["id"], "revenue_usd": revenue})
else:
below_threshold.append({"domain": item["id"], "revenue_usd": revenue})
return jsonify({
"qualified": qualified,
"below_threshold": below_threshold,
"unknown": unknown,
"min_revenue": min_revenue,
"max_revenue": max_revenue,
})
if __name__ == "__main__":
app.run(port=5012)
5. Run the application
python app.py
curl -s -X POST http://localhost:5012/qualify-by-revenue \
-H "Content-Type: application/json" \
-d '{"domains": ["clay.com"], "min_revenue": 50000000, "max_revenue": 500000000}'
6. Verify the result
This example was tested live against 1 real domain.
{
"below_threshold": [],
"max_revenue": 500000000,
"min_revenue": 50000000,
"qualified": [{"domain": "clay.com", "revenue_usd": 100000000}],
"unknown": []
}
A negative-control test confirmed the "unknown, never disqualified" rule: setting min_revenue above a known real value correctly moved it to below_threshold (a real value outside the range), while a genuinely non-existent domain correctly landed in unknown rather than below_threshold.
How it works
Company Revenue (Exact) is a waterfall function — Clay's own description states it cross-checks multiple data providers to return the most accurate figure. Its result is always a string of digits, which is why the service parses to int before any numeric comparison.
Common issues
Comparing "100000000" > 50000000 raises TypeError
Cause: the API returns revenue as a string, not a number.
Fix: always int() the value before comparing, and handle the case where parsing fails by routing to unknown.
A domain with real, known funding ends up in unknown
Not necessarily a bug: this specific routine can legitimately have no data for a given company even when other Clay functions (e.g. funding lookups) do. Report it as unknown, don't infer a revenue value from unrelated signals.
Next steps
- Check recent funding as a budget-availability signal — see the Clay recently-funded-companies example
- Combine with a firmographic score — see the Clay firmographic lead-scoring example
- Source the domain list first — see the Clay TAM-by-industry example
Verification
verification:
status: verified
tested_at: "2026-08-18"
product_version: "public/v0"
command: "python app.py && curl -s -X POST http://localhost:5012/qualify-by-revenue -d '{\"domains\":[\"clay.com\"],\"min_revenue\":50000000,\"max_revenue\":500000000}'"
expected_result: "HTTP 200, clay.com qualified with revenue_usd=100000000"