BetterContact queries multiple data vendors for each contact and returns the best result, in batches of up to a hundred. Emails are cheap. Phone numbers cost roughly ten times as much, so hyreflow leaves them switched off unless you ask for them.
Another waterfall option. It runs after the shortlist exists and before anything is validated.
start from companies with a live hiring signal
the deliverability gate after the waterfall
the alternative waterfall, worth trying on a thin batch
send to the addresses that came back clean
Ask for the outcome and your agent composes the run itself. Or start from a skill, a whole pipeline it already knows end to end.
browse all skills →Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.
Read the BetterContact docs →HOW in lib/bettercontact.py. Docs cached at reference/docs/bettercontact/raw/.
https://app.bettercontact.rocks/api/v2 · Auth: header X-API-Key (env BETTERCONTACT_API_KEY; never hardcode).start_enrichment(data=[{first_name,last_name,company,company_domain,linkedin_url,...}], enrich_email_address=True, enrich_phone_number=False, webhook=None) → POST /async → returns {id}. Max 100 leads/request.get_enrichment(request_id) → GET /async/{request_id} — poll until terminal (or use webhook).enrich_phone_number=True raises the charge from 0.5 to 4.8 credits (billed once, on retrieval, when the result carries data) — default off, enable only when a phone number is actually needed. Pilot a small batch first.Waterfall enrichment layer (multi-provider email/phone). Take a shortlist → BetterContact → validate (Enrichley/email-validation) → ATS/sequencer.
Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper /
result.data.prefix).
start_enrichment returns a request id immediately -> fetch terminal data via get_enrichment(request_id).deliverable > catch_all_safe > catch_all_not_safe > undeliverable - only trust deliverable and catch_all_safe for outreach.enrich_phone_number: true when explicitly needed. get_enrichment returns credits_consumed.lib/bettercontact.pyImport: from lib.bettercontact import BetterContact → instantiate BetterContact() (reads key from env). Base: https://app.bettercontact.rocks/api/v2. Generic passthrough: request(method, path, *, params, json).
get_enrichment(request_id: str) -> dict — GET /async/{request_id} — poll the enrichment result.start_enrichment(data: list[dict], *, enrich_email_address: bool = True, enrich_phone_number: bool = False, webhook: str | None = None, **opts) -> dict — POST /async — start waterfall enrichment for up to 100 leads. Returns {id}.