Blog/enrichment
1 min read

Automate Email-to-Profile Enrichment, End to End

Turn a list of emails into full person profiles with People Data Labs on Monid, one pay-per-call lookup each, written straight to your sheet or CRM.

Automate Email-to-Profile Enrichment, End to End

Copy this line to your agent to turn a list of emails into full person profiles.

set up https://monid.ai/SKILL.md and use pdl /v5/person/enrich to resolve an email to a full profile

You can turn a raw list of emails into full person profiles (name, job title, employer, location, seniority, social handles) with one pay-per-call lookup per address, and write each clean row straight to a sheet or CRM. Monid is a pay-per-call data API marketplace: one key and one wallet reach hundreds of external data endpoints across enrichment, scraping, social data, and search, with the price shown before anything runs. This is the cookbook version. Follow the steps, copy the code, and by the end you have a loop that takes emails.csv in and hands profiles.csv out.

TL;DR

  • The endpoint is People Data Labs /v5/person/enrich on Monid. It matches one email against roughly three billion profiles and returns a full person record, billed per call.
  • Reading the schema is free, so you inspect the exact inputs and returned fields before you spend a cent, then run a single email to sanity check it.
  • The fields that carry a CRM row are full_name, job_title, job_title_levels, job_company_name, location_name, and the social handles, plus a likelihood score to gate trust.
  • Batch is a shell loop: read each address, run the lookup, pull six fields with jq, append a row. A hundred emails lands in the tens of dollars.
  • One key, one wallet, no per-seat enrichment subscription. In a month you enrich nobody, you pay nothing.

What you are wiring up

emails.csv in, one enriched row per person out. Person enrichment is the pricier corner of the catalog, so do it deliberately: it bills per call, on the order of tens of cents each, not the fraction of a cent a social scraper costs. The whole job is deciding which emails deserve a lookup and reading only the fields you will act on.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More details in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add --label main --key <your-api-key>

More details in the CLI quickstart.

Step 1. Inspect the endpoint (free)

Read the schema before you spend anything. inspect returns the exact input shape, the price, and the docs, and it never bills.

monid inspect -p pdl -e /v5/person/enrich
# input:   email | phone | name (or first_name + last_name) + company
#          | profile (LinkedIn URL) | pdl_id | email_hash
#          knobs: min_likelihood (1-10, default 2), required,
#          data_include, titlecase
# returns: full_name, job_title, job_title_levels, job_company_name,
#          location_name, linkedin/twitter/github, work_email, likelihood
# price:   PER_CALL

Three knobs here are worth setting up front, and they are what keep the bill honest:

  • min_likelihood floors the match confidence on a 1 to 10 scale. The default of 2 is loose. For anything that writes a name into a CRM, raise it, because greeting the wrong person by name is worse than an empty cell.
  • required lets you say "only count this a match if it comes back with an email and a job title". A response missing your must-have fields returns no match, so you are not paying full price for a shell record.
  • titlecase cleans JANE DOE into Jane Doe on the way out, which saves a normalization pass before the row hits a sheet.

The docs for every returned field are in the PDL person enrichment reference.

Step 2. Run one email

Prove the loop on a single address before you point it at the whole list. Body JSON goes to -i, and -w waits for the result inline instead of making you poll.

monid run -p pdl -e /v5/person/enrich \
  -i '{"email": "dana@northwind-logistics.com",
       "min_likelihood": 6, "titlecase": true,
       "required": "emails AND job_title"}' -w
# -> one person record, price shown before it executes

If you would rather save the raw record to disk (handy while you are still eyeballing the shape), grab the run by id instead:

monid runs get -r 01HXYZ... -o person.json

Step 3. Read the fields that matter

A full record is large, but a routed, contactable CRM row needs six things. Here is what each one does for you:

FieldWhat it isWhat you do with it
full_namethe person, title-casedthe greeting line, no cleanup
job_titlecurrent role textsubject-line relevance
job_title_levelsseniority (e.g. cxo, manager)route VPs to a human, ICs to nurture
job_company_namecurrent employeraccount matching in the CRM
location_namecity, region, countrythe timezone you send in
linkedin_username, twitter_url, github_urlsocial handlesthe follow-up channel when email bounces

The social handles are the quiet upgrade over a plain name-and-title enrichment. An email that goes cold still leaves you a LinkedIn profile to connect on or a GitHub to read, so a non-reply is not a dead end. And job_title_levels is the field that lets the routing run itself: it is a normalized array, so you branch on cxo or director in code without parsing free text.

Step 4. Batch the list

Now scale it. Read emails.csv one line at a time, run each address, and append the six fields as a row. Keep min_likelihood where you set it so a weak match writes nothing rather than a wrong somebody.

echo "name,title,seniority,company,location,linkedin" > profiles.csv

while IFS= read -r email; do
  monid run -p pdl -e /v5/person/enrich \
    -i "{\"email\": \"$email\", \"min_likelihood\": 6, \"titlecase\": true}" \
    -w -o - \
  | jq -r '[.data.full_name,
            .data.job_title,
            (.data.job_title_levels // [] | join("|")),
            .data.job_company_name,
            .data.location_name,
            .data.linkedin_username] | @csv' >> profiles.csv
done < emails.csv

A no-match row comes back empty, so a quick jq 'select(.data.full_name)' filter drops the misses before they clutter the sheet. And because every call prints its price before it bills, you can run the first ten rows, read the tally, then let the rest of the file through.

Step 5. Wire it into your flow

profiles.csv imports straight into most CRMs, but you rarely want a manual import in the loop. Two ways to close it:

  • Push each row as you go. Swap the >> profiles.csv append for a curl to your CRM's contacts endpoint, mapping job_title_levels to your lead-tier field. Now enrichment and CRM write are one pass.
  • Hand it to an agent. Because Monid ships as an MCP server, an agent handed "enrich this week's signups and tag anyone senior" can read the sheet, run each lookup, keep the confident matches, and write the rest to a review queue. Free discovery and a visible per-call price are what make handing it the wallet feel safe.

Either way the shape is the same as the figure: read a row, run one call, keep six fields, move to the next.

What the run actually costs

Person enrichment bills per call, and the magnitude is the honest headline here. Each lookup is on the order of tens of cents, not the fraction of a cent a social scraper costs, and you see the exact number before every run. The live prices are at monid.ai/tools.

Inspect the schema        free
Run one test email        one call, tens of cents
Batch of 100 signups      ~100 calls, lands in the tens of dollars
No-match rows             filtered, but a matched call still bills
------------------------------------------------------------------
Typical weekly pass: one call per address you chose to enrich

Set that against a seat-based enrichment subscription, which charges a fixed monthly seat whether you enrich two thousand people or none, and usually meters credits you lose at renewal. Here you pay for the calls you make and nothing in the weeks you make none, which fits list enrichment exactly: bursty before a campaign, quiet in between. The lever on cost is Step 1, not a contract. Skip the free-mail signups, set required so shell records do not bill full freight, and every address you enrich is one you meant to.

FAQ

Do I need a People Data Labs account? No. You integrate Monid once and fund one pay-as-you-go wallet. PDL is called through the same key, and the wallet bills at the price shown before each run.

What if an email does not match anyone? You get no match rather than a wrong one. Set min_likelihood around 6 for anything customer-facing, and use required to insist a match carry the fields you need before it counts.

How much does a list cost to enrich? Per call, on the order of tens of cents each, so a hundred emails lands in the tens of dollars and a handful of inbound checks is pocket change. Current per-endpoint prices are at monid.ai/tools.

Can I enrich something other than an email? Yes. The same /v5/person/enrich accepts a phone, a name plus company, a LinkedIn URL, an email_hash if the raw address is sensitive, or a PDL id. Pass whatever identifier you hold.

Run it on your list

Take the last export of signups you never got around to researching. Inspect the endpoint for free, run ten addresses pay-per-call, and see how many turn into rows you can act on. If the fields check out, let the loop run the rest. Start at monid.ai.

enrichmentpeople data labsemailcrm