Skip to content

Enrichment

The enrichment endpoints cover three capabilities:

  • Lookup — Find a single person or company from the open data index when you already know their email, LinkedIn URL, or domain. Returns full profile data instantly.
  • Enrich — Fill missing fields (emails, phone numbers) on contacts you already have in your workspace by running them through multiple data providers in sequence (waterfall enrichment).
  • Verify — Check if an email address is deliverable before sending.

Two billing buckets

Enrichment endpoints split into two buckets that bill differently. The split matters because graph8 owns the cost on one side and pays a third-party provider on the other.

Index Lookups - free on both plans

These endpoints hit graph8’s owned indexes (OpenSearch + ClickHouse). Single-record, instant, no waterfall.

EndpointPAYGPlatform
POST /enrichment/lookup/personFree (within 5 rps)Free (within 5 rps)
POST /enrichment/lookup/companyFree (within 5 rps)Free (within 5 rps)
POST /enrichment/verify-email (internal validator)Free (within 5 rps)Free (within 5 rps)

Waterfall Enrichment - always credits

These endpoints chain through external providers (Prospeo, Dropcontact, Cognism, and others). graph8 pays the provider per record - so credits apply on both PAYG and Platform.

EndpointPAYGPlatform
POST /enrichment/enrich (waterfall)Variable per recordVariable per record
External email verifiers (Kickbox, ZeroBounce)Per-verificationPer-verification

See Pricing for the full plan comparison.


Person Lookup

POST /enrichment/lookup/person

Instant person lookup. Provide at least one of: email, linkedin_url, or first_name + last_name + company_domain.

Pricing: Free on both PAYG and Platform within the 5 rps cap (graph8-owned index data).

Request Body

FieldTypeRequiredDescription
emailstringNo*Work email address
linkedin_urlstringNo*LinkedIn profile URL
first_namestringNo*First name (requires last_name + company_domain)
last_namestringNo*Last name (requires first_name + company_domain)
company_domainstringNo*Company domain (requires first_name + last_name)

*At least one lookup strategy is required.

Example

Terminal window
curl -X POST "https://be.graph8.com/api/v1/enrichment/lookup/person" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "jane@acme.com"}'

Response

{
"data": {
"found": true,
"confidence": 0.95,
"data": {
"first_name": "Jane",
"last_name": "Doe",
"job_title": "VP of Sales",
"company": "Acme Inc",
"linkedin_url": "https://linkedin.com/in/janedoe",
"work_email": "jane@acme.com"
}
}
}

Company Lookup

POST /enrichment/lookup/company

Instant company lookup by domain or name.

Pricing: Free on both PAYG and Platform within the 5 rps cap (graph8-owned index data).

Request Body

FieldTypeRequiredDescription
domainstringNo*Company domain
namestringNo*Company name

*At least one of domain or name is required.

Example

Terminal window
curl -X POST "https://be.graph8.com/api/v1/enrichment/lookup/company" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"domain": "acme.com"}'

Response

{
"data": {
"found": true,
"confidence": 0.98,
"data": {
"name": "Acme Inc",
"domain": "acme.com",
"industry": "Technology",
"employee_count": 500,
"annual_revenue": "$50M-$100M"
}
}
}

Start Enrichment Job

POST /enrichment/enrich

Start an async waterfall enrichment job. The job runs across multiple data providers and returns a job_id you can poll for results.

Returns 202 Accepted.

Pricing: Credits apply on both PAYG and Platform - waterfall enrichment hits third-party providers (Prospeo, Dropcontact, Cognism, etc.) with per-record cost. Cost varies by which providers are configured in fields_config.

Request Body

FieldTypeRequiredDescription
contact_idsinteger[]YesContact IDs to enrich
list_idintegerYesList ID the contacts belong to
fields_configobjectNoFields to enrich and provider order (see below)

fields_config example:

{
"work_email": ["prospeo", "dropcontact"],
"direct_phone": ["cognism", "lusha"]
}

If omitted, defaults to {"work_email": ["prospeo", "dropcontact"]}.

Example

Terminal window
curl -X POST "https://be.graph8.com/api/v1/enrichment/enrich" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact_ids": [101, 102, 103],
"list_id": 5,
"fields_config": {"work_email": ["prospeo", "dropcontact"]}
}'

Response

{
"data": {
"job_id": "abc-123-def",
"status": "queued"
}
}

Poll Enrichment Job

GET /enrichment/jobs/{job_id}

Check the status of an enrichment job.

Status Values

StatusDescription
queuedJob is waiting to start
runningEnrichment in progress
completedAll contacts processed
failedJob failed

Example

Terminal window
curl "https://be.graph8.com/api/v1/enrichment/jobs/abc-123-def" \
-H "Authorization: Bearer $API_KEY"

Response

{
"data": {
"job_id": "abc-123-def",
"status": "completed"
}
}

Verify Email

POST /enrichment/verify-email

Verify a single email address and check its deliverability status.

Pricing: Free on both PAYG and Platform within the 5 rps cap when graph8’s internal validator can answer. Calls that fall through to third-party verifiers (Kickbox, ZeroBounce) consume 1 credit per verify on both plans.

Request Body

FieldTypeRequiredDescription
emailstringYesEmail address to verify

Example

Terminal window
curl -X POST "https://be.graph8.com/api/v1/enrichment/verify-email" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "jane@acme.com"}'

Response

{
"data": {
"email": "jane@acme.com",
"status": "valid",
"sub_status": null,
"is_valid": true
}
}
StatusDescription
validDeliverable email address
invalidUndeliverable
catch-allDomain accepts all addresses
unknownCould not determine

Waterfall Credit Matrix

Waterfall enrichment (POST /enrichment/enrich) runs each contact / company through a sequence of 14 third-party providers. Only successful provider hits charge credits — if no provider matches, the entire run is free. Cached results (same record + field, within the 7-day cache TTL) also return for free.

Per-provider hit cost

ProviderReturnsEmailPhoneOther
ApolloEmail, phones, title, seniority, company, LinkedIn12 (direct), 2 (mobile)LinkedIn 1, title 1
HunterEmail, domain1Domain 1, verify 2
ProspeoEmail, direct phone12
DropContactEmail, phone, company12 (direct), 2 (mobile)
LushaEmail, direct + mobile phone12 (direct), 2 (mobile)
IcypeasEmail, phone, LinkedIn, title, company11Domain 0.5, LinkedIn 1, company 1
RocketReachEmail, phone, company, LinkedIn222
LeadMagicEmail, mobile, LinkedIn, company, industry, funding0.53 (mobile)LinkedIn 3, company 2, funding 2.5
ClearbitCompany domain, industry, headcount, title2
BuiltWithCompany tech stack, domain relationships2 per action
SemrushTraffic, keywords, competitors, social1 per result returned
graph8 internalMashup contacts + companies2 per lookup (free if using org-owned API key)

Email verifier add-on cost

Run after a provider returns an email; if invalid the waterfall continues to the next provider.

ProviderVerify costNotes
LeadMagic0.5Cheapest option
EmailListVerify1Dedicated verifier
ZeroBounce1 (verify) / 20 (find_email)Find_email is the expensive outlier
Icypeas1Also a data-finding provider
Hunter2Slightly higher than competitors

Default waterfall order

Email (work_email / contact_email): Apollo → Hunter → Prospeo → DropContact → Lusha → Icypeas → RocketReach → LeadMagic → (optional verifier: EmailListVerify / ZeroBounce).

Direct phone: Apollo → Prospeo → DropContact → Lusha.

Mobile phone: Apollo → DropContact → Lusha → LeadMagic.

Company domain: Clearbit → Apollo → Hunter.

Industry / size: Clearbit only.

Order is configurable per org via the in-app waterfall editor — enrichment_configs row drives the live sequence.

When credits are (and aren’t) charged

ScenarioCharged?
Provider returns a matchYes — cost of that field for that provider
Provider returns no matchNo — waterfall moves on
All providers exhausted, no matchNo charge at all
Cached result returned (same field, same record, within 7d TTL)Free
Provider call uses your own API key (configured in the org)Free
Record skipped because run conditions weren’t metFree
Email verifier validates an email as validVerifier cost absorbed; no extra charge
Email verifier rejects an emailVerifier cost charged; waterfall continues for free

Apollo phone-reveal flags

Apollo offers two add-on flags that cost extra credits beyond the base hit:

FlagExtra credits
reveal_phone_numbers=true+3 to +15 (depends on number type)
reveal_personal_emails=true+1 to +7

Both flags default to off to avoid surprise spend. Enable per call when you specifically need direct phone or personal email.

Credit hold + batch charge

For large enrichment jobs the system pre-holds a credit budget then charges in batches:

  1. Job start: hold total_records × max_per_record × 1.25 (25% safety buffer).
  2. Per record completion: pending credits accumulate.
  3. Every 100 records: pending → charged from the hold.
  4. Job complete: remaining pending charged, unused hold released back to balance.

Use GET /enrichment/jobs/{job_id} to monitor pending vs charged credits mid-run.

Pricing examples

ScenarioCost
Enrich a contact, Apollo finds work email on first hit1 credit
Enrich a contact, no provider matches0 credits
Enrich a contact, need both work email + direct phone, Apollo matches both1 + 2 = 3 credits
Re-enrich the same contact within 7 days0 credits (cache hit)
Bulk enrich 1,000 contacts, ~70% find rate, avg 1.2 credits per hit~840 credits