Skip to content
Finowl

Guides

CRM data enrichment guide: clean, enrich and keep contacts fresh

A CRM data enrichment guide: dedupe and normalize contacts, add aggregate gender insight and breach exposure flags, map fields and set a refresh cadence.

A CRM is only as useful as the data inside it. Duplicates inflate counts, messy email addresses break matching, and stale fields send teams in the wrong direction. Enrichment can add real value on top, but only after the basics are clean.

This guide covers the full loop: cleaning and deduplicating contacts, enriching them with the Finowl API for audience insight and security signals, mapping results into CRM fields, and keeping everything fresh without wasting credits.

Step 1: clean before you enrich

Every record you enrich costs a credit, so enriching duplicates and malformed rows is paying twice for bad data. Cleaning first also makes the enriched data easier to trust.

Normalize email addresses

Email is usually the best key for matching contacts. Normalize it consistently before any comparison:

  • Trim leading and trailing whitespace.
  • Lowercase the whole address. The local part is technically case-sensitive, but in practice almost every mail provider treats it as case-insensitive, and lowercasing avoids most duplicates.
  • Strip display names such as "Alex Doe" <alex@example.com> down to the plain address.
  • Flag addresses that fail basic validation instead of guessing a fix.

Finowl accepts plain addresses with a dotted domain, without display names, quoted local parts or IP-address domains, up to 254 characters. Requests that fail those rules are rejected with invalid_input and are free, but validating locally keeps your job logs clean and gives you a list of records for someone to fix.

Be careful with provider-specific tricks like removing dots or +tag suffixes. They are valid for some mail providers and wrong for others, so only apply them where you know the rule holds, and keep the original address.

Deduplicate contacts

With normalized emails, deduplication becomes a grouping problem. Group by normalized email, then pick a surviving record using clear rules: most recently updated, most complete, or the one linked to an active deal. Merge useful fields from the others and archive the rest.

Contacts without an email need a different key, such as normalized name plus company domain. Treat those matches as suggestions for human review rather than automatic merges.

Split names into usable parts

Many CRMs store a single "Full name" field. For name-based enrichment you need the given name. Split carefully and keep the original. Records with only initials, company names or role addresses like sales@ should be marked as not eligible for name enrichment.

Step 2: decide what to enrich and why

Enrichment should serve specific teams with specific questions. Two common ones fit Finowl well.

Aggregate audience insight for marketing

Marketing teams often want to understand the rough composition of an audience, for example the gender mix of newsletter subscribers by region. Name-based gender predictions can answer that question in aggregate.

The key word is aggregate. A prediction is a statistical estimate of how a name is typically used, not how a person identifies, and it is wrong for some people. Use it for analytics and low-stakes personalization only, never for eligibility, pricing, access or decisions with significant effects on a person. Let people state or correct their own gender, and when they do, their answer replaces the prediction. Mention name-based lookups in your privacy notice, because names are personal data. Our post on responsible gender prediction goes deeper on these guardrails.

In practice this means building reports from counts and shares by segment, rather than exposing a per-contact gender field to every CRM user.

Breach exposure flags for security teams

For B2B products, knowing that a customer admin's email appears in recent breaches is a useful security signal. The security team can prioritize multi-factor authentication outreach or watch those accounts more closely. The email breach API returns each breach's Name, AddedDate, DataClasses and verification flags, which you can reduce to a few CRM-friendly fields.

These flags are sensitive. Store them where only the security team can see them, not as a column every sales rep can export.

Step 3: run the enrichment

Batch gender lookups

The batch endpoint accepts 1 to 50 items per request, each with a unique id (up to 64 characters), a type of name, email or username, a value and an optional country hint. A batch counts as one request against the 60 requests per minute rate limit, which makes it the right tool for CRM-scale work.

python
import os
import requests

URL = "https://api.finowl.co/v1/gender/batch"
HEADERS = {
    "Authorization": f"Bearer {os.environ['FINOWL_API_KEY']}",
    "Content-Type": "application/json",
}

contacts = [
    {"crm_id": "003A1", "first_name": "Jane", "country": "US"},
    {"crm_id": "003A2", "first_name": "Andrea", "country": "IT"},
    {"crm_id": "003A3", "first_name": "Kim", "country": "KR"},
]

items = [
    {"id": c["crm_id"], "type": "name", "value": c["first_name"], "country": c["country"]}
    for c in contacts
]

resp = requests.post(URL, json={"items": items}, headers=HEADERS, timeout=60)
resp.raise_for_status()

for item in resp.json()["data"]:
    if "error" in item:
        print(item["id"], "failed:", item["error"]["code"])
        continue
    pred = item["data"]
    print(item["id"], pred["result_status"], pred["gender"], pred["confidence"])

A few details matter here. Batch items default to ai_mode: "off", so they use the dataset only and cost 1 credit each. Validation is all or nothing: one invalid item rejects the whole batch with no charge. A 200 response can still contain item-level errors, each with its own charged_credits value. Never resend a whole batch because one item failed; retry only the failed items, and only where it is safe. The batch gender enrichment guide and our post on how to batch enrich 100k contacts cover throttling and retries at scale.

Breach checks

Email breach checks run one address per request. At 60 requests per minute, plan for roughly 3,600 checks an hour and schedule large lists across several runs. Handle 429 rate_limited by waiting for the Retry-After header, and stop the job on quota_exceeded.

Step 4: map results into CRM fields

Design your fields so that consumers can tell what a value means and how fresh it is.

CRM field Source Notes
gender_estimate data.gender when confidence is high Restricted; used for aggregates
gender_estimate_confidence data.confidence Keep alongside the estimate
breach_exposed breached Security team only
latest_breach_added max AddedDate Drives alerting and refresh

Some practical rules:

  • Only write gender_estimate when result_status is identified and confidence passes your threshold. Leave it empty for unknowns.
  • Keep a separate gender_self_reported field. It always wins over the estimate.
  • Store an enriched_at timestamp for each enrichment type.
  • Do not store the full breach Description in the CRM. Fetch details on demand when someone investigates.

Step 5: set a refresh cadence

Different fields go stale at different speeds.

Gender estimates rarely need refreshing

The way a name is typically used does not change month to month. Enrich once when a contact is created or their name changes, and skip contacts with a self-reported value.

Breach flags need regular checks

New breaches are added continuously, so a clean result today can change next month. Re-check active contacts monthly or quarterly depending on your risk, and compare the latest AddedDate to detect new exposure.

Only enrich what changed

Trigger enrichment from CRM change events where possible: new contact, changed email, changed name. Combined with a periodic breach sweep, this keeps data fresh while spending credits only where something changed.

Budgeting the work

Each lookup or batch item costs 1 credit, or 3 credits when a gender lookup requests AI. Every account gets 100 free credits a month. For a CRM of 50,000 deduplicated contacts, a one-time gender pass is about 50,000 credits, and a monthly breach sweep of 10,000 active admin contacts adds 10,000 credits a month. Prepaid packs never expire, so a Growth pack of 500,000 credits for $249 could cover both for a long time. See pricing for all pack sizes.

Frequently asked questions

Should I deduplicate CRM contacts before enrichment?

Yes. Each lookup costs a credit, so enriching duplicates wastes money and creates conflicting values. Normalize emails, merge duplicates, then enrich the surviving records.

Can I use gender predictions to segment individual contacts?

Predictions are best used for aggregate audience insight and low-stakes personalization. Never use them for eligibility, pricing, access or decisions with significant effects, and always let a person's self-reported gender override the estimate.

How often should CRM enrichment be refreshed?

Gender estimates rarely need refreshing unless a name changes. Breach flags should be re-checked monthly or quarterly, because new breaches are added all the time.

What happens if one item in a batch fails?

The rest of the batch still succeeds, and the failed item comes back with an error and its own charged_credits value. Retry only the failed items where safe, and never resend the whole batch.

All articles