Docs
Guides

Enrich your leads

Fill work emails, mobile phones, LinkedIn URLs, and company facts onto a table you already have, for a cost you approve first.

Start from a table whose rows carry one identity signal each: a LinkedIn profile URL, or a full name plus a company domain.

Add the column in the app

Open Tables in the sidebar, open your table (/tables/<id>), then click the + at the right end of the column header row (tooltip: Add column).

The Tools panel opens on its Internal tab, which starts with Most used: AI, Work email, Mobile phone, Person enrichment, Company enrichment and Email verification. Two of them are bundles: Person enrichment (one LinkedIn profile lookup, then 13 free formula columns — headline, bio, location, followers, full/first/last name, job title, current company, current company LinkedIn URL, job start date, education, school — needs a LinkedIn URL column; rows without one are skipped and cost nothing) and Company enrichment (one company lookup, about 1 credit a company, then 8 free formula columns — name, domain, LinkedIn URL, headcount, industry, description, founded year, HQ country — with the whole profile kept in its JSON column; needs a domain or company LinkedIn URL column, rows with neither are skipped and cost nothing, and it auto-binds to a current_company_linkedin_url column left by Person enrichment). Clicking one asks which column holds its input, then creates the whole bundle and opens the one paid column; nothing runs until you run it. The tab has more company bundles, each one paid lookup column that fills its own columns: Tech stack (the technologies a company runs), Funding (total raised, latest round, number of rounds and investors), Revenue (estimate) (a figure or a range), Hiring signals (the roles it is hiring for, with a count) and Lookalike companies (companies similar to each seed company). Each is priced per row before it runs; from the CLI, oxygen columns add <table> --preset company_funding adds one (or company_tech_stack, company_revenue, company_hiring, company_lookalikes). Work email and Mobile phone are single-field waterfalls; LinkedIn URL (a person's profile URL from their full name plus their company's domain, name or LinkedIn page) sits under Enrich person further down the tab. The Integrations tab holds single-vendor tools rather than waterfalls.

Choosing an entry creates the column and opens its editor:

  • The provider lanes, in the order they run (a LinkedIn URL column shows none). A column made in the app routes each row by the inputs it has; to force one keying on a work-email column, pass --email-waterfall-profile (auto, name_domain, linkedin_url or first_last_domain) to oxygen enrich-column preview and oxygen enrich-column run.
  • Input mapping — map your row columns onto the canonical inputs. A column with nothing mapped cannot run.
  • Email verification (work email only) — a toggle. On, every found address is verified before it lands in the cell.
  • Estimated cost — the typical spend, with the worst case shown as "up to".

Nothing is charged yet. The footer has Save without running and Run; Run offers Run for first 10 rows, Run for next 25 rows, Run missing results, Rerun full table, and selected rows, then a cost step showing Estimated credits, Rows affected, Per row, Recommended cap, Available, and a Max credits field ("Hard cap on credits spent. The run stops before exceeding it."). Credits move only when you confirm that step.

A workspace table grid with typed columns

Why a waterfall is cheaper than one provider

Lanes run in order and a row stops at the first lane that returns a result. On OXYGEN’s managed credentials, billing depends on the intent: work email and phone bill on a hit — a lane that finds nothing releases its reservation, so a row resolved early never pays the lanes behind it. Company-field enrichment bills every lane it attempts, hit or miss, except its domain ↔ LinkedIn URL and company-profile lookups, which bill only on a hit. A LinkedIn URL costs a flat 5 credits when one is found that matches the person (9.2 while OXYGEN’s managed LinkedIn rail runs on HarvestAPI), and nothing when none is. Full rules: tool costs. On Auto, a lane a row cannot drive is skipped, so a row with only a name and domain never pays for a LinkedIn-keyed provider. On work email, that row first checks up to eight guessed addresses through the email verifier. Each check costs 0.225 credits, even when no email is found (guessed-address checks). To skip them, pass --email-pattern-validation disabled to oxygen enrich-column run. Switching Email verification off skips them too, along with the check on found addresses. On managed work email, phone and LinkedIn URL there is nothing to gate, because a lane that misses costs nothing; --allow-premium-lanes only matters on intents that bill every attempt. Successful calls on your own provider key pay the separate platform fee even on a miss, and a dispatched own-key miss is not retry-safe. Your provider may charge separately, outside the OXYGEN credit cap. See own-key fees and retries.

The same thing from the CLI

Preview first. It makes no provider calls and costs nothing:

oxygen enrich-column preview leads \
  --capability work_email \
  --linkedin-url-column linkedin_url \
  --company-domain-column domain \
  --limit 10 --json

Read expected_credits (typical), estimated_credits (worst case), recommended_max_credits, estimated_row_count, selected_providers, blocked_providers, and runnable.

The next command spends credits. --approved authorizes this one run; --max-credits is the ceiling it cannot cross.
oxygen enrich-column run leads \
  --capability work_email \
  --linkedin-url-column linkedin_url \
  --company-domain-column domain \
  --only-missing \
  --max-credits 200 \
  --approved --json

--capability also takes mobile_phone and linkedin_url; add --verify-phone to get line type and carrier. Follow the run with oxygen table-runs wait <run-id> --json and oxygen table-runs provider-summary <run-id> --json. The response's web_url opens the same run in the app.

Three errors stop this command:

  • approval_required (exit 7) — you left off --approved. Read the preview, then retry with it.
  • selection_required — pass --limit <n>, --all, or --only-missing.
  • invalid_enrichment_mapping — no provider can run on the columns you mapped. Map a LinkedIn URL column, or a name column plus --company-domain-column.

What lands in the table

A work_email run writes email, email_provider, email_status, and email_enriched_at, plus the JSON column work_email_enrichment holding every attempt. A mobile_phone run writes mobile_phone_e164, phone_source, phone_line_type, phone_carrier, phone_enrichment_status, and phone_enriched_at.

Read a cell before you trust it

Unsettled cells wear a chip: Queued, Running, Retrying, Rate limited, Failed. A settled cell shows none, so a blank cell with no chip means the waterfall ran and found nothing — not that it never ran.

Double-click a cell (or select it and press Enter) to open Cell details: Last run (Status, Attempts, Completed), the Value tree, and Rerun this cell. The hover button on a filled cell's right edge is Expand into result columns — or Expand sub-columns on the column header — which fans the waterfall out into one column per provider attempt; clicking one opens it as a Waterfall attempt.

Same data on the terminal:

oxygen cells inspect leads <row-id> work_email_enrichment --json

One row, no table

Each lookup previews for free (dry_run is the default) and needs --mode live --max-credits <n> to actually spend:

oxygen find email --full-name "Ada Lovelace" --company-domain acme.com --json
oxygen find email --full-name "Ada Lovelace" --company-domain acme.com --mode live --max-credits 20 --json
oxygen find personal-email --linkedin-url https://www.linkedin.com/in/ada --json
oxygen find personal-email --linkedin-url https://www.linkedin.com/in/ada --mode live --max-credits 20 --json
oxygen find person --linkedin-url https://www.linkedin.com/in/ada --json
oxygen find person --linkedin-url https://www.linkedin.com/in/ada --mode live --max-credits 10 --json

oxygen find phone, oxygen find linkedin, and oxygen find company --fields headcount,industry,funding_stage,latest_funding_round,revenue,technologies,job_openings take the same two modes. find personal-email finds a personal (non-work) address through its own managed lane (see oxygen enrichment catalog --intent find_personal_email), billed only on a hit and graded by MillionVerifier. find person runs Blitz first (about 1 credit) and the managed LinkedIn lookup only when Blitz has no profile, each billed only on a hit (given only an email or a name, it first finds the LinkedIn URL, priced like find linkedin). It returns the full profile block — name, current company, title, job start date, education, headline, bio, location, and follower count (from the LinkedIn lookup only). With no identity signal at all they fail with missing_identity_input. oxygen find company --list-fields prints the whole company field catalog (identity, firmographics, funding, relationships, signals, technology, web presence) with each field's per-row credits: a free field is read from the profile the run already fetched, a fixed field costs one priced lane, and an ~estimated field walks a cascade that bills only on a hit. An unknown field key is refused, never silently replaced by the defaults. Revenue is in that catalog only as an estimate (revenue: a figure when a source has one, otherwise a range), because no provider reports exact revenue for private companies. Valuation is not in it: it comes from the company_valuation_estimate_v1 column template as a labelled estimate with a range, and company_revenue_estimate_v1 does the same for revenue.

Verify addresses you already have

oxygen verify email [email protected] --json
oxygen verify email [email protected] --mode live --max-credits 40 --json

The free first call returns estimate.recommended_max_credits — use that number, because catch-all addresses escalate to a second, dearer verifier. Verdicts are valid, invalid, catch_all, or unknown; see Email verification before you filter on them.

Company facts across the table

oxygen companies enrich preview leads --missing-fields domain,linkedin_url,headcount,industry --limit 10 --json
oxygen companies enrich run leads --missing-fields domain,linkedin_url,headcount,industry --limit 100 --approved --max-credits 150 --json

More on the mechanics: Waterfalls, Cells, Spend caps.

On this page