Waterfall enrich HubSpot contacts across Apollo, Clearbit, and PDL using Make
Prerequisites
- Make account (Core plan or higher recommended for complex routing)
- HubSpot connection configured in Make via OAuth
- Apollo API key (Settings → Integrations → API)
- Clearbit API key (API → API Keys in dashboard)
- People Data Labs API key (from PDL dashboard)
Overview
Make's Router and Filter modules are a natural fit for waterfall logic. You'll route the contact through up to three enrichment providers, with filters checking whether more data is needed at each stage.
Step 1: Create the scenario and trigger
Add a HubSpot CRM module:
- Module: Watch Contacts
- Watch: New contacts only
- Limit: 10 per poll
Set the scenario schedule to every 15 minutes (Free plan) or every 1 minute (Core plan and above).
Step 2: Call Apollo (first provider)
Add an HTTP module (Make a request):
- URL:
https://api.apollo.io/api/v1/people/match - Method: POST
- Headers:
x-api-key: YOUR_APOLLO_KEY,Content-Type: application/json - Body type: Raw → JSON
- Content:
{
"email": "{{1.properties.email}}"
}Step 3: Evaluate Apollo results and set variables
Add a Set Multiple Variables module (under Tools) to normalize the Apollo response into a flat structure:
| Variable Name | Value |
|---|---|
jobtitle | {{2.person.title}} |
company | {{2.person.organization.name}} |
phone | {{2.person.phone_numbers[1].sanitized_number}} |
linkedin_url | {{2.person.linkedin_url}} |
industry | {{2.person.organization.industry}} |
source | apollo |
The first phone number is phone_numbers[1], not phone_numbers[0].
Step 4: Route to Clearbit if fields are missing
Add a Router module after the variable-setting step.
Route 1 — All fields filled (skip to HubSpot update):
- Add a Filter on this route
- Label: All fields present
- Condition:
jobtitleexists ANDcompanyexists ANDphoneexists
Route 2 — Missing fields (call Clearbit):
- Add a Filter on this route
- Label: Missing fields
- Condition:
jobtitledoes not exist ORcompanydoes not exist ORphonedoes not exist
On Route 2, add an HTTP module for Clearbit:
- URL:
https://person.clearbit.com/v2/people/find?email={{1.properties.email}} - Method: GET
- Headers:
Authorization: Bearer YOUR_CLEARBIT_KEY
Add another Set Multiple Variables module to merge Clearbit data into gaps. Use Make's ifempty() function:
| Variable Name | Value |
|---|---|
jobtitle | {{ifempty(3.jobtitle; 5.title)}} |
company | {{ifempty(3.company; 5.employment.name)}} |
linkedin_url | {{ifempty(3.linkedin_url; "https://linkedin.com/in/" + 5.linkedin.handle)}} |
source | {{3.source}} + clearbit |
(Module numbers will vary based on your scenario layout.)
Step 5: Route to PDL if fields are still missing
Add another Router after the Clearbit merge step with the same pattern:
Route 1 — All fields filled → proceed to update Route 2 — Still missing → call PDL
On Route 2, add an HTTP module for PDL:
- URL:
https://api.peopledatalabs.com/v5/person/enrich - Method: POST
- Headers:
x-api-key: YOUR_PDL_KEY,Content-Type: application/json - Body:
{
"email": "{{1.properties.email}}"
}Add a Set Multiple Variables module to merge PDL data:
| Variable Name | Value |
|---|---|
jobtitle | {{ifempty(6.jobtitle; 8.data.job_title)}} |
company | {{ifempty(6.company; 8.data.job_company_name)}} |
phone | {{ifempty(6.phone; 8.data.phone_numbers[1])}} |
source | {{6.source}} + pdl |
The PDL enrichment API returns person fields nested under a data key. Access fields as {{module.data.job_title}}, not {{module.job_title}}.
Step 6: Update the HubSpot contact
All three routes converge on a HubSpot CRM module:
- Module: Update a Contact
- Contact ID:
{{1.id}} - Job Title:
{{jobtitle}} - Company Name:
{{company}} - Phone:
{{phone}}
For custom properties, use an HTTP module:
- Method: PATCH
- URL:
https://api.hubapi.com/crm/v3/objects/contacts/{{1.id}} - Body:
{
"properties": {
"jobtitle": "{{jobtitle}}",
"company": "{{company}}",
"phone": "{{phone}}",
"linkedin_url": "{{linkedin_url}}",
"industry": "{{industry}}",
"enrichment_source": "{{source}}"
}
}Step 7: Add error handling and activate
- Add Resume error handlers (with 5-second delay) on each HTTP module — this handles rate limit
429responses - Add a Break error handler on the final HubSpot Update for manual retry of failed writes
- Click Run once to test the full waterfall
- Check each module's output to verify data merging
- Toggle the scenario to Active
Cost and credits
- Make Free plan: 1,000 credits/month. A full waterfall (all 3 providers) uses ~8-10 credits per contact. Apollo-only uses ~4 credits.
- Make Core plan: $29/mo for 10,000 credits. Handles ~1,000-2,500 enrichments/month depending on waterfall depth.
- Apollo: 1 credit/enrichment ($49/mo = 900 credits)
- Clearbit: Volume-based pricing starting at $99/mo
- PDL: $0.03-0.10/enrichment, pay-as-you-go available
- Typical cost: If Apollo covers 70% of contacts fully, you'll call Clearbit for 30% and PDL for 10%. For 100 contacts: 100 Apollo + 30 Clearbit + 10 PDL calls.
Next steps
- Add a Data Store — log which provider filled which fields to evaluate ROI per provider
- Reorder the waterfall — test with Clearbit first if your ICP skews toward well-known companies (Clearbit has stronger coverage for enterprise)
- Add domain filtering — skip personal email domains before the waterfall to conserve credits across all three providers
Need help implementing this?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.