CRM data enrichment for developers

Your CRM is full of sparse records. Name and email — maybe. Job title — sometimes. Company size, industry, phone number — rarely. And the data you do have is decaying at 22-30% per year as people change jobs, companies get acquired, and phone numbers go stale.

The standard solution is to buy another SaaS tool: Clay, ZoomInfo, Apollo, or one of the dozens of CRM enrichment platforms that charge per seat, per month, and require yet another dashboard to manage.

If you're a developer, there's a better way.

The Problem with CRM Enrichment Platforms

They're Expensive

ZoomInfo starts at ~$15,000/year. Clay starts at $149/month. Apollo charges per seat. For a startup or small team, these prices are absurd for what amounts to a data lookup service.

They Add Another Dashboard

You already have a CRM. Now you need a separate enrichment platform with its own login, its own UI, its own learning curve. Some of these platforms are genuinely complex — Clay has an entire spreadsheet-like interface with formulas and waterfall logic.

They're Designed for Sales Ops, Not Developers

The enrichment happens through a GUI: upload a CSV, click "enrich," wait for results, download. Or set up a Zapier/Make integration that runs on triggers. Either way, it's point-and-click automation — not code.

They Lock You In

Most CRM enrichment platforms want to own your workflow. They encourage you to build sequences, campaigns, and automations inside their platform instead of your CRM. Now you have two systems to maintain.

The Developer Approach

Instead of adding another platform, use a CLI tool to enrich CRM data programmatically:

$ salesforce query "SELECT Email FROM Contact WHERE Industry = null" > unenriched.csv

$ cat unenriched.csv | while read email; do
    enrich email "$email" --json
  done > enriched.jsonl

$ cat enriched.jsonl | your-crm-update-script

No new dashboard. No per-seat pricing. Just a script that runs when you need it.

Practical Workflows

1. Enrich on Import

When new contacts are added to your CRM (from a form, CSV import, or API), enrich them immediately:

#!/bin/bash
# enrich-new-contacts.sh
# Run after every batch import

NEW_CONTACTS="$1"

while IFS=',' read -r name email; do
    enriched=$(enrich email "$email" --json 2>/dev/null)
    if [ $? -eq 0 ]; then
        title=$(echo "$enriched" | jq -r '.person.title // empty')
        company=$(echo "$enriched" | jq -r '.company.name // empty')
        industry=$(echo "$enriched" | jq -r '.company.industry // empty')
        headcount=$(echo "$enriched" | jq -r '.company.headcount // empty')

        echo "$name,$email,$title,$company,$industry,$headcount"
    else
        echo "$name,$email,,,,"
    fi
done < "$NEW_CONTACTS" > enriched_import.csv

echo "Enriched $(wc -l < enriched_import.csv) contacts"

2. Nightly Enrichment of Sparse Records

Set up a cron job that finds CRM records missing key fields and enriches them:

#!/bin/bash
# nightly-enrich.sh
# Cron: 0 2 * * * /path/to/nightly-enrich.sh

# Query CRM for contacts missing job title
psql -c "SELECT email FROM contacts WHERE title IS NULL AND email NOT LIKE '%gmail%' LIMIT 100" \
  -t -A | while read email; do
    result=$(enrich email "$email" --json 2>/dev/null)
    if [ $? -eq 0 ]; then
        title=$(echo "$result" | jq -r '.person.title // empty')
        company=$(echo "$result" | jq -r '.company.name // empty')
        if [ -n "$title" ]; then
            psql -c "UPDATE contacts SET title='$title', company='$company' WHERE email='$email'"
        fi
    fi
done

3. Re-Enrich Stale Records

Contacts older than 6 months probably have decayed data. Re-enrich them:

#!/bin/bash
# re-enrich-stale.sh

# Find contacts enriched more than 6 months ago
psql -c "SELECT email FROM contacts WHERE enriched_at < NOW() - INTERVAL '6 months' LIMIT 200" \
  -t -A | while read email; do
    enrich email "$email" --json 2>/dev/null
done > refreshed.jsonl

echo "Re-enriched $(wc -l < refreshed.jsonl) stale records"

With enrichcli, cached results are free. If a person's data hasn't changed, the cache returns the existing data at no credit cost. You only pay for genuinely new lookups.

4. Lead Scoring Script

Enrich leads and automatically score them based on company size and seniority:

#!/bin/bash
# score-leads.sh

while read email; do
    data=$(enrich email "$email" --json 2>/dev/null)
    [ $? -ne 0 ] && continue

    name=$(echo "$data" | jq -r '.person.name')
    title=$(echo "$data" | jq -r '.person.title')
    headcount=$(echo "$data" | jq -r '.company.headcount')

    score=0

    # Score by seniority
    case "$title" in
        *CEO*|*CTO*|*VP*|*Director*) score=$((score + 30)) ;;
        *Manager*|*Lead*|*Head*) score=$((score + 20)) ;;
        *) score=$((score + 10)) ;;
    esac

    # Score by company size
    case "$headcount" in
        *1000*|*5000*|*10000*) score=$((score + 30)) ;;
        *100*|*200*|*500*) score=$((score + 20)) ;;
        *) score=$((score + 10)) ;;
    esac

    echo "$email,$name,$title,$headcount,$score"
done < leads.txt | sort -t',' -k5 -rn > scored_leads.csv

CRM-Specific Integration Tips

Salesforce

Use the Salesforce CLI (sf) alongside enrichcli:

$ sf data query -q "SELECT Id, Email FROM Contact WHERE Title = null" --json \
  | jq -r '.result.records[] | [.Id, .Email] | @csv' > to_enrich.csv

$ while IFS=',' read -r id email; do
    data=$(enrich email "$email" --json 2>/dev/null)
    [ $? -ne 0 ] && continue
    title=$(echo "$data" | jq -r '.person.title // empty')
    echo "$id,$title"
  done < to_enrich.csv > updates.csv

$ sf data bulk upsert -s Contact -f updates.csv -i Id

HubSpot

Use HubSpot's API alongside enrichcli:

$ curl -s "https://api.hubapi.com/crm/v3/objects/contacts?properties=email,jobtitle&limit=100" \
    -H "Authorization: Bearer $HUBSPOT_TOKEN" \
  | jq -r '.results[] | select(.properties.jobtitle == null) | .properties.email' \
  | while read email; do
    enrich email "$email" --json
  done > hubspot_enriched.jsonl

Any CRM with a REST API

The pattern is always the same:

  1. Query your CRM for records missing data
  2. Enrich those records with enrichcli
  3. Update your CRM with the enriched data

The specific API calls change, but the enrichment step is always the same: enrich email "$email" --json.

Cost Comparison

Running CRM enrichment with enrichcli vs. dedicated platforms:

Scenarioenrichcli CostClay CostApollo Cost
500 contacts/month$29/month (Pro)$149/month$49/user/month
2,000 contacts/month$79/month (Growth)$149/month$79/user/month
5,000 contacts/month$79/month (Growth)$349/month$119/user/month
10,000 contacts/month$199/month (Team)$800/month$119/user/month x seats

No per-seat pricing. No annual contracts. Cached re-enrichments are free.

When to Use a Platform Instead

Be honest: CLI-based enrichment isn't for everyone.

Use a platform (Clay, Apollo, etc.) if:

  • Your team is non-technical and needs a GUI
  • You need waterfall enrichment across 10+ data providers
  • You want built-in email sequences alongside enrichment
  • You need native Salesforce/HubSpot sync without writing code

Use enrichcli if:

  • You're comfortable writing shell scripts
  • You want enrichment as part of a data pipeline
  • You want simple, credit-based pricing
  • You're building custom workflows that platforms can't support
  • You're a developer who prefers code over dashboards

Getting Started

$ brew install enrichcli/tap/enrichcli

$ enrich email someone-from-your-crm@company.com --json

$ vim enrich-crm.sh

50 free enrichments per day. Start by enriching your 50 most important sparse contacts and see what you get back.

start enriching data from the command line.

get started free

50 free enrichments per day. no credit card required.