Enrich Airtable leads with verified emails and load Instantly
When a new lead lands in Airtable, find a verified work email and mobile, write the data back to the row, and push it into the right Instantly campaign.
Build me a code workflow that enriches new leads in my Airtable Outbound Targets table with verified contact data from Prospeo, writes the enriched fields back to the row, and loads the lead into a configured Instantly campaign. Every step is deterministic, no agent loop.
Trigger: poll Airtable using the new_record event on my Outbound Targets table. The user picks the base, table, and optionally a view at setup time. Each polled row is one workflow run.
Step 1. Read the Airtable row. The fields I care about are: first_name, last_name, company_domain, linkedin_url, and personalization_snippet (a short Airtable column with a one-line hook for the email). Treat first_name + last_name as required, and require at least one of company_domain or linkedin_url. If those minimum inputs are missing, skip the run, write "Missing required fields" into a Status column on the row via Airtable Update Record, and end.
Step 2. Call Prospeo Enrich Person with first_name, last_name, and whichever of company_domain or linkedin_url is populated (prefer company_domain when both are present). Set enrich_mobile to true so we pull a verified mobile number alongside the verified work email. Set only_verified_email to true so we never receive a guessed address. Prospeo returns a top-level error boolean. If error is false, read verified email, mobile, current job title, company name, company domain, company LinkedIn URL, and company size from the response.
Step 3. Handle the no-match case. If Prospeo returns error true with error_code NO_MATCH, or returns an empty email field, do not push to Instantly. Instead call Airtable Update Record on the original row and set Status to "Skipped (no verified email)" plus a Skipped At timestamp, then end the run. If Prospeo returns INSUFFICIENT_CREDITS or RATE_LIMITED, surface that as a workflow error so the user sees it on the run and can top up or back off — do not mark the row skipped in that case.
Step 4. On a successful enrichment, call Airtable Update Record on the original row and write back: verified_email, mobile, current_title, company_name, company_size, and Status = "Enriched". Use the field names above as defaults but make them configurable at setup so users with different schemas can map their own column names.
Step 5. Call Instantly Add Leads in Bulk against a campaign UUID the user configures at setup (or, optionally, read the campaign UUID off a column on the row so different segments can go to different campaigns). Send exactly one lead per call: first_name, last_name, email (the verified email from Prospeo), company_name (from Prospeo), and a custom_variables object containing first_name, title (from Prospeo), company (from Prospeo), and personalization (the personalization_snippet from Airtable). Instantly only accepts strings, numbers, booleans, or null inside custom_variables, so coerce accordingly and drop any null personalization rather than sending the literal string "null".
Step 6. Read the Instantly response. If the lead was uploaded, call Airtable Update Record one more time to set Status = "Loaded to Instantly", write the returned Instantly lead UUID into an Instantly Lead ID column, and stamp the Loaded At timestamp. If Instantly skipped the lead (blocklisted, duplicate, invalid), set Status = "Instantly skipped" and write the skip reason into an Error column so the RevOps owner can see why it did not load. Do not retry skipped leads automatically; the row stays in the table with the error recorded.
Batching note: if multiple rows are returned by a single Airtable poll, the workflow can batch the Prospeo step into a single Bulk Enrich Person call (up to 50 prospects per call) instead of one Enrich Person call per row, then fan back out for the per-row Airtable updates and the per-row Instantly Add Leads in Bulk calls. Single-row enrich is fine if batching adds complexity.
Configurable at setup: the Airtable base, table, view; the field names for first_name, last_name, company_domain, linkedin_url, personalization_snippet, verified_email, mobile, current_title, company_name, company_size, Status, Error, Instantly Lead ID, Loaded At, and Skipped At; whether the Instantly campaign UUID is a single fixed value or read from a row column; and the campaign UUID itself.
Credentials needed: Airtable (OAuth with data.records:read and data.records:write on the base), Prospeo (API key), and Instantly (API v2 key with leads:create and leads:read scopes, or all:all).
Additional information
What does this prompt do?
- Watches your Airtable outbound target table and fires the moment a new row appears.
- Looks up the prospect on Prospeo using first name, last name, and either a company domain or LinkedIn URL to find a verified work email, mobile number, current title, and company details.
- Writes the verified contact info back to the Airtable row so your records stay clean and exportable.
- Pushes the enriched lead into the Instantly campaign you choose, with first name, title, company, and a personalization snippet mapped to your campaign template. Skips the lead if Prospeo cannot verify an email, so your Instantly deliverability stays high.
What do I need to use this?
- An Airtable base with a target table that holds at least first name, last name, and either a company domain or a LinkedIn URL.
- A Prospeo account with credits available for person enrichment.
- An Instantly account on the Growth plan or higher with the campaign you want leads loaded into already set up.
How can I customize it?
- Map which Airtable columns hold first name, last name, domain, LinkedIn URL, and the personalization snippet sent into Instantly.
- Decide which Instantly campaign each lead goes into, either a single campaign for the whole table or a campaign ID read off a column on each row so different segments go to different sequences.
- Change what happens when Prospeo cannot verify an email, for example route the row into a manual review view instead of marking it skipped.
Frequently asked questions
What happens if Prospeo cannot find a verified email?
Can I run this on rows that only have a LinkedIn URL?
How fast does a new Airtable row sync to Instantly?
Will it overwrite my existing Airtable columns?
Does this work with the Instantly Free plan?
Stop loading Instantly with guessed emails.
Connect Airtable, Prospeo, and Instantly once, and Geni only loads leads with a verified work email, with the rest waiting in Airtable for review.