Waterfall enrich HubSpot contacts across Apollo, Clearbit, and PDL using Make

high complexityCost: $10-29/mo

Prerequisites

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 NameValue
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}}
sourceapollo
Remember: Make uses 1-based arrays

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: jobtitle exists AND company exists AND phone exists

Route 2 — Missing fields (call Clearbit):

  • Add a Filter on this route
  • Label: Missing fields
  • Condition: jobtitle does not exist OR company does not exist OR phone does 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 NameValue
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 NameValue
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
PDL nests data under 'data'

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

  1. Add Resume error handlers (with 5-second delay) on each HTTP module — this handles rate limit 429 responses
  2. Add a Break error handler on the final HubSpot Update for manual retry of failed writes
  3. Click Run once to test the full waterfall
  4. Check each module's output to verify data merging
  5. 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.