Monthly HubSpot contact refresh with Lusha and a Sheets audit log
On the 1st of every month, refresh stale or incomplete HubSpot contacts with Lusha, write the fresh data back, and log every change to a Google Sheet.
Build a code workflow that runs on the 1st of every month at 2am and refreshes stale or incomplete HubSpot contacts with Lusha, logging every batch to a Google Sheet. There are no LLM steps. Everything is deterministic: search, batch enrich, batch upsert, append row.
Trigger: cron, 1st of each month at 2am in the user's timezone.
Step 1. HubSpot Search Contacts. Use a filter group that matches contacts where email is empty OR phone is empty OR lastmodifieddate is older than 6 months ago. Page through results 100 at a time using the cursor returned in paging.next.after. Request the properties: email, firstname, lastname, phone, mobilephone, jobtitle, company, website, linkedinbio (or whatever the org's LinkedIn URL property is called, fall back to no LinkedIn if unset), lastmodifieddate.
Step 2. For each page of up to 100 contacts, call Lusha Enrich People (Bulk). Build one contact object per HubSpot record using the best identifier available, in this priority order: (a) existing email, (b) full name plus company domain derived from the website or email domain, (c) full name plus LinkedIn URL. Skip any HubSpot record that has none of those. Lusha's bulk endpoint caps at 100 per request, which matches the HubSpot page size exactly, so one HubSpot page maps to one Lusha bulk call.
Step 3. From the Lusha response, build a HubSpot Batch Upsert Contacts payload matched on the email property. For each Lusha hit, write back: email (the Lusha-verified one), mobilephone (Lusha mobile), jobtitle, company. Skip the upsert entry for any contact Lusha did not return data for. Keep a running count for the batch: processed, updated, not_found, credits_used (sum of isCreditCharged === true across the response objects).
Step 4. After each batch (immediately after the upsert), call Google Sheets Append Values on the configured audit-log spreadsheet and tab. Append one row with these columns in order: run_timestamp (ISO 8601), batch_index (1-based), contacts_processed, contacts_updated, contacts_not_found, credits_consumed. Use valueInputOption USER_ENTERED so the timestamp parses as a date in the sheet.
Loop until HubSpot search returns no paging.next. Respect rate limits: HubSpot Search is 4 requests per second per token, and Lusha enrichment is 25 requests per second. Add a short pause between batches if needed. On a 429 from either side, honor Retry-After and continue.
Setup inputs the workflow should ask for: the Google Sheets spreadsheet ID, the tab name for the audit log, and the staleness threshold in months (default 6). Everything else uses the defaults above.
Additional information
What does this prompt do?
- Finds HubSpot contacts that are missing an email or phone, or that have not been updated in the last 6 months.
- Sends those contacts to Lusha in batches and pulls back fresh email, mobile phone, job title, and company.
- Writes the fresh data back to the matching HubSpot contacts so your CRM stays clean without anyone clicking refresh.
- Appends one summary row to a Google Sheet after every batch with the run time, how many contacts were processed, how many were updated, how many Lusha did not find, and how many credits were used.
What do I need to use this?
- A HubSpot account where you can connect contacts read and write access.
- A Lusha account with API access on a paid plan.
- A Google Sheet you want to use as the audit log, plus a Google account that can write to it.
How can I customize it?
- Change the schedule. Monthly at 2am is the default, but weekly or quarterly works just as well.
- Tighten or loosen the filter. The default targets contacts missing email or phone, or not updated in 6 months. You can swap in your own staleness window or property checks.
- Change which fields get written back. Default is email, mobile phone, job title, and company. Add or drop any HubSpot property you want kept fresh.
- Point the audit log at a different sheet or tab, or add extra columns like the Lusha run ID or the person responsible.
Frequently asked questions
How often does it run?
Will it re-enrich contacts that already look complete?
What gets written back to HubSpot?
How will I know what was changed?
Will this work on the HubSpot Free plan?
What happens if Lusha can't find a contact?
Stop letting your CRM rot one stale record at a time.
Connect HubSpot, Lusha, and Google Sheets once. Geni keeps your contacts fresh and writes a paper trail every month.