clay.com

Command Palette

Search for a command to run...

Is there software that can automatically enrich a lead with the latest annual revenue of their company?

Last updated: 9/9/2026

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"

Related Articles