DOCS / HOW TO / ENRICH COMPANIES FOR OUTREACH
VIEW RAW

Enrich companies for outreach

A walkthrough that turns a list of domains into outside-in labour-cost business cases you can pull straight into an outreach pipeline. You enrich domains into your company library, read the ready-made wage narrative and per-function breakdown per company, then export the library as CSV or JSON for your sequencer. Every example uses plain curl against POST /v1/companies and friends, so it works from any stack.

Before you start

  • A workspace on humanhours.dev (Hobby is fine while you validate; Hobby includes 10 one-time research lookups).
  • An API key: /api-keys → Generate key. The raw hh_live_… value shows once. Copy it into HUMANHOURS_API_KEY.
  • A list of company domains you want to reach out to.

A research lookup is the unit of cost. It is consumed only when a domain is newly enriched into your library or refreshed. Listing, fetching, and exporting your library are always free, so you can pull for outreach as often as you like.

Step 1 · Add one company

Enrich a single domain. This call is synchronous: it researches the domain inline (typically 15-30 seconds) and returns the full record, charging one lookup because the company is new to your library.

curl -X POST https://humanhours.dev/api/v1/companies \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "stripe.com",
    "external_id": "acct_123",
    "tags": ["outreach-q3"]
  }'

You get back { "company": { ... }, "charged": true } with a 201. Tag every company you enrich (here outreach-q3) so you can filter the export later. Re-running this exact call returns the same record for free with charged: false; pass ?refresh=true only when you want fresh research and accept another lookup.

Step 2 · Bulk import a list

For more than a handful of domains, use the bulk endpoint. It is asynchronous: it dedupes and validates the input, queues a background job, and returns 202 immediately. Nothing is charged at submission. The worker charges one lookup per domain as it processes, and only on success.

curl -X POST https://humanhours.dev/api/v1/companies/bulk \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domains": ["stripe.com", "vercel.com", "supabase.com"],
    "tags": ["outreach-q3"]
  }'

Response:

{
  "job_id": "job_9f2c...",
  "accepted": 2,
  "rejected": 0,
  "duplicates_removed": 1,
  "status": "queued"
}

duplicates_removed is 1 here because stripe.com was already in your library from Step 1. Now poll the job until it is done:

curl https://humanhours.dev/api/v1/jobs/job_9f2c... \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY"
{
  "job_id": "job_9f2c...",
  "status": "running",
  "input_count": 3,
  "accepted": 2,
  "processed_count": 1,
  "error_count": 0,
  "percent": 50
}

Poll every few seconds until status is done. Domains that fail enrichment land in error_count and are not charged.

Step 3 · Read the business case

Each enriched company carries a business_case you can put straight in front of a prospect. Fetch one record (free):

curl https://humanhours.dev/api/v1/companies/stripe.com \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY"

The fields that drive outreach:

  • business_case.summary is the outreach-ready narrative. It states the role mix, the largest function and its hourly wage, and the annual wage bill in plain language. Drop it into a first-touch message.
  • roles and wages give the per-function breakdown: headcount and hourly wage per function. The largest function and its wage are your hook, telling you which team to lead with.
  • confidence.overall (a 0..1 score) tells you how much to lean on the numbers. The breakdown is per dimension (wages, headcount, roles) and honest: a record with cited wages but a soft headcount estimate shows high confidence.wages and lower confidence.headcount. Wages come from official labour statistics where available, each cited in sources. Treat every figure as an outside-in estimate to validate on the call, not as ground truth.

Step 4 · Export the library for outreach

When the job is done, pull the whole tagged set in one request. This is free and repeatable.

CSV for a spreadsheet or sequencer import:

curl "https://humanhours.dev/api/v1/companies?format=csv&tag=outreach-q3" \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY" \
  -o outreach-q3.csv

The CSV flattens the headline business-case fields per company (domain, company name, wage bill, summary, confidence, and your tags). See the Companies API reference for the exact column order.

JSON when you want the full structured record (roles, wages, sources) in code:

curl "https://humanhours.dev/api/v1/companies?format=json&tag=outreach-q3&limit=1000" \
  -H "Authorization: Bearer $HUMANHOURS_API_KEY"

limit defaults to 500 and maxes at 1000.

Watch out for

  • lookup_quota_exceeded: you hit your plan's monthly research-lookup cap. There are no overages, so enrichment stays blocked until you upgrade at /billing. Listing and exporting your existing library keep working.
  • Bulk costs are deferred, not free: the 202 charges nothing, but each successful domain costs one lookup as the worker runs. Check accepted to know how many lookups the job will consume.
  • Already-owned domains are free: re-listing or re-fetching never costs a lookup. Only new enrichment and explicit refresh do.

Found a typo or want to suggest an edit? Email support@triadagency.ai.