Fill in missing mobile numbers on HubSpot contacts overnight
Every night at 2am, find contacts with no mobile number, look them up in bulk, and write the results back so your reps stop hitting dead ends.
Every night at 2am on a cron schedule, fill in the missing mobile numbers on my HubSpot contacts so my reps stop hitting dead ends. This is a deterministic pipeline with a fixed query, a fixed enrichment job, and a fixed write-back. There are no judgement calls anywhere in it.
Step 1, select the records. Use HubSpot Search Contacts to pull contacts where the mobile phone property (mobilephone) is empty, the lifecycle stage (lifecyclestage) is one of the stages I care about (default to lead and salesqualifiedlead, and make the list configurable), and my enrichment attempted date property has never been set. Cap the result at a fixed number of records per run, default 500, exposed as config so credit spend per run is predictable. Request the properties needed to identify a person for lookup: first name, last name, email, company, and LinkedIn URL if I store one. If the search returns zero contacts, post nothing and end the run quietly.
Step 2, build the CSV. Turn those rows into a CSV with a header row and one column per identifying field, plus a hubspot_contact_id column carrying the record id. Keep an in-workflow map from row to HubSpot contact id as well, keyed on record id and on email as a fallback, so matching back does not depend on Boomerang echoing the id column. Because the CSV has a header row, omit columnMappings and let Boomerang auto-detect the columns. If the submit returns a 400 with code COLUMN_MAPPING_ERROR, read details.missingRequired, details.outOfRange and details.duplicateColumns, report them in the Slack failure message, and make no CRM writes.
Step 3, submit the job. Use the Boomerang Submit Mobile Finder Enrichment operation, which is a bulk multipart form upload with the CSV as the file part. Configure whether US numbers and UK numbers should be included, as two booleans, defaulting both to true. Capture the returned request id and the credits reserved at submit time.
Step 4, poll for completion. Call Get Request Status on that request id until the status leaves "In queue". The status values are exactly "In queue", "Completed" and "Issue", capitalized and with a space, so compare against them exactly. Poll about once a minute with a sensible backoff and an overall timeout of roughly two hours, after which treat the run as failed. Boomerang is rate limited to 60 requests per minute and 600 per hour per key, so if any call returns 429, honor the Retry-After header value in seconds before retrying.
Step 5, on "Completed", download the output. Read outputUrl off the status response and fetch the CSV. That link is a time-limited signed URL, and outputUrlExpiresAt gives its expiry, so if it has expired just re-poll the request to mint a fresh one. Important: do not read the emailFound or phoneFound fields to decide whether the run worked. Those stay null even on completed jobs until Boomerang's data team populates them. The output CSV is the source of truth for what was found.
Step 6, write the numbers back. Match each output row back to its HubSpot contact id using the id column and the fallback map, then write the mobile numbers in with HubSpot Batch Update Contacts, chunked into batches of at most 100 records per request, which is that operation's limit. Only set the mobile phone property on rows that actually came back with a number.
Step 7, stamp everything that was attempted. Set the enrichment attempted date property (for example mobile_enrichment_attempted_date) to today's date on every contact that was submitted, including the ones that came back empty. This is the part that matters most: it is what makes the step 1 query skip them next time, so I never pay twice to look up the same dead record. Fold these into the same batches of 100 where possible.
Step 8, log every result. Append one row per submitted contact to a Google Sheets audit tab using Append Values, whether or not a number was found. Include the run date, contact id, name, company, lifecycle stage, a found or not found flag, and the number that was written when there is one. This is what lets me see hit rate over time and work out which segments are worth enriching.
Step 9, summarize to Slack. Use Slack Bot Send a Message to post a short overnight summary to my chosen channel with records submitted, numbers found, hit rate as a percentage, and credits used. Take credits used from creditsUsed on the status response, which is the amount actually charged, rather than the credits reserved at submit.
Failure path. If the job comes back with status "Issue", or the submit fails with a 402 meaning insufficient credits or an exhausted free-tier cap, or the poll times out, post that to Slack instead of the summary and make no CRM writes at all. Do not stamp the attempted date on contacts that were never actually looked up, because that would silently blacklist them from every future run.
Build the nightly batch rather than a per-contact version. The mobile finder is a bulk CSV job with batch pricing and a per-key hourly request budget, so firing one asynchronous job per newly created contact burns the budget and wastes the batch rate. A HubSpot triggered per-contact variant is a reasonable customization to mention, but the scheduled batch is the shape to build.
What does this prompt do?
- Every night it pulls the contacts in your CRM that are missing a mobile number and still sit in the lifecycle stages you care about, such as lead or sales qualified lead.
- It sends that batch off for a bulk mobile number lookup, waits for the job to finish, and writes any numbers that come back onto the right contact records.
- Every contact it tried gets stamped with the date it was attempted, so future runs skip it and you never pay twice to look up the same dead record.
- Every result, found or not found, is appended to a Google Sheet so you can watch your hit rate over time, and a short summary lands in Slack before you start the day.
What do I need to use this?
- A HubSpot account with permission to read and update contacts.
- A Boomerang account with enough credits to cover the records you look up each night.
- A Google Sheet with a tab set aside for the enrichment log.
- A Slack workspace and a channel for the overnight summary.
- One extra date field on your HubSpot contacts to record when enrichment was last attempted. Your admin can add this in a minute.
How can I customize it?
- Change the run time or the nightly record cap to control exactly how much you spend per run.
- Choose which lifecycle stages get enriched, and whether US and UK numbers are included in the lookup.
- Log more than the basics by adding columns to the audit tab, such as owner or original source, so you can see which segments actually return numbers.
- Run it per contact instead of nightly. HubSpot can tell the workflow the moment a contact is created, though the nightly batch is usually cheaper and easier on lookup limits.
FAQs
Will this overwrite mobile numbers I already have?
What happens to contacts where no number is found?
How do I keep the cost predictable?
What if the lookup fails or I run out of credits?
Will this work on HubSpot Free?
Why does it run overnight instead of the moment a contact is created?
Related templates
Stop buying stale lists. Reps run a saved search, work the results like an inbox, and only the accounts they approve ever reach your CRM.
Pick a date, a starting point and a radius, then build a sequenced day of customer visits that lands straight on your calendar.
See how your brand's news coverage and sentiment stack up against four competitors, then let an assistant write the weekly report for you.
One screen where reps filter for companies that fit, see who is actually reachable at each account, and save only the addresses that verify.
One screen showing every social post waiting on approval, sorted by deadline, so reviewers can approve or reject without leaving the page.
Every Monday, find the past champions and closed-won contacts who changed jobs, update Attio, and get the moves worth chasing in Slack.
Stop handing your reps contacts with no phone number.
Set this up once and every lead worth calling gets a mobile number filled in overnight, with a log that shows exactly what you got for your credits.