Batch enrich HubSpot contacts missing job title or company size using Make
Prerequisites
- Make account (Free plan works for small batches; Core plan recommended for larger volumes)
- HubSpot connection configured in Make via OAuth
- Apollo API key with enrichment credits
Step 1: Create the scenario and schedule it weekly
Create a new scenario. Set the schedule:
- Schedule type: At regular intervals
- Run scenario: Every week
- Day: Sunday
- Time: 22:00
- Timezone: Your team's timezone
Step 2: Search for contacts missing fields
Add an HTTP module (Make an API Call):
- URL:
https://api.hubapi.com/crm/v3/objects/contacts/search - Method: POST
- Headers: Authorization handled by HubSpot connection
- Body:
{
"filterGroups": [{
"filters": [{
"propertyName": "jobtitle",
"operator": "NOT_HAS_PROPERTY"
}]
}],
"properties": ["email", "firstname", "lastname", "jobtitle", "company", "phone", "linkedin_url", "industry"],
"limit": 100
}To find contacts missing any critical field, use separate filterGroups. Each group is ORed together. This finds contacts where title OR company is empty, catching more gaps in a single search.
Step 3: Iterate over contacts
Add an Iterator module:
- Array:
{{1.results}}
Each contact is emitted as a separate bundle.
Step 4: Call Apollo for enrichment
Add an HTTP module:
- URL:
https://api.apollo.io/api/v1/people/match - Method: POST
- Headers:
x-api-key: YOUR_APOLLO_KEY,Content-Type: application/json - Body:
{
"email": "{{2.properties.email}}"
}Add a Filter on the connection after Apollo:
- Condition:
personexists
Apollo returns {"person": null} when it can't find a match — not an error. Without the filter, downstream modules would try to read properties from null and fail. Always filter on person existence.
Step 5: Build the update payload (only empty fields)
Add a Code module (Core plan required) to build a properties object that only includes fields currently missing from the contact:
const contact = input.iteratorBundle; // from Iterator
const person = input.person; // from Apollo
const properties = {};
if (!contact.properties.jobtitle && person.title) {
properties.jobtitle = person.title;
}
if (!contact.properties.company && person.organization?.name) {
properties.company = person.organization.name;
}
if (!contact.properties.phone && person.phone_numbers?.[0]?.sanitized_number) {
properties.phone = person.phone_numbers[0].sanitized_number;
}
return {
contactId: contact.id,
properties,
hasUpdates: Object.keys(properties).length > 0,
};Alternatively, on the Free plan, use Set Multiple Variables with ifempty():
| Variable | Value |
|---|---|
jobtitle | {{ifempty(2.properties.jobtitle; 3.person.title)}} |
company | {{ifempty(2.properties.company; 3.person.organization.name)}} |
phone | {{ifempty(2.properties.phone; 3.person.phone_numbers[1].sanitized_number)}} |
Make's ifempty(a; b) returns a if it has a value, or b if a is empty. This means existing HubSpot data is preserved — Apollo only fills gaps.
Step 6: Filter and update HubSpot
Add a Filter:
- Condition:
hasUpdatesequalstrue(or check that at least one variable is non-empty)
Add an HTTP module:
- Method: PATCH
- URL:
https://api.hubapi.com/crm/v3/objects/contacts/{{4.contactId}} - Headers: Authorization via HubSpot connection
- Body:
{
"properties": {
"jobtitle": "{{4.properties.jobtitle}}",
"company": "{{4.properties.company}}",
"phone": "{{4.properties.phone}}",
"enrichment_date": "{{formatDate(now; 'YYYY-MM-DD')}}",
"enrichment_source": "apollo"
}
}Step 7: Add rate limiting and error handling
- Add a Sleep module (500ms) after the Apollo call within the Iterator loop
- Add a Resume error handler on the Apollo HTTP module (handles
429rate limits) - Add a Break error handler on the HubSpot PATCH module for manual retry of failed writes
- Click Run once to test
- Toggle the scenario to Active
Cost and credits
- Make Free plan: 1,000 credits/month. Each contact uses ~4-5 credits. Handles ~200-250 contacts/month.
- Make Core plan: $29/mo for 10,000 credits. Handles ~2,000-2,500 contacts/month.
- Apollo: 1 credit per person enrichment. Basic plan ($49/mo) = 900 credits. At 50 contacts/week, that's 200 credits/month.
- Weekly batch of 50 contacts: ~200-250 Make credits + 50 Apollo credits.
Each bundle from the Iterator passes through every downstream module, and each module execution counts as 1 credit. For 50 contacts with 4 downstream modules, that's 200 credits per run. Monitor credit usage in Make's dashboard.
Next steps
- Handle pagination — add a loop for the HubSpot search to process all pages, not just the first 100 results
- Add a Data Store — log enrichment results to Make's Data Store for audit and reporting
- Multi-field search — expand the search filters to catch contacts missing company, phone, or LinkedIn in addition to job title
- Add Slack summary — append a Slack module to post batch results: "Enriched 42/50 contacts this week"
Need help implementing this?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.