Push new Airtable leads into Instantly and HubSpot
When a new lead lands in your Airtable outbound queue, add it to the right Instantly campaign and mirror it into HubSpot in one pass.
Build me a code workflow that pushes new leads from my Airtable outbound queue into Instantly and mirrors them into HubSpot, in one deterministic pass per row.
Trigger: poll Airtable using the new_record event on my Outbound Queue table. The user will pick 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: email, first_name, last_name, company, title, instantly_campaign_id (the campaign UUID this lead should go into), and any custom variable columns such as icebreaker and personalization_line. Treat instantly_campaign_id and email as required; if either is missing, skip the row and write "Missing email or campaign" into the Error column on that row using Airtable Update Record, then end the run.
Step 2. Call Instantly Add Leads in Bulk against the campaign UUID on the row. Map first_name, last_name, email, company_name, and personalization (title) into the Instantly lead schema. Put any extra Airtable columns I flagged as custom variables into the lead's custom_variables object (Instantly only accepts strings, numbers, booleans, or null as values, so coerce accordingly). Send exactly one lead per call (this row), with skip_if_in_workspace and skip_if_in_campaign both off unless the user opts in. Read the response: Instantly returns counts for total_sent, leads_uploaded, skipped_count, and an array describing each skipped lead with its reason (blocklisted, duplicate, invalid email, etc.).
Step 3. If the lead was uploaded successfully, call HubSpot Batch Upsert Contacts with idProperty set to email. Set properties: email, firstname, lastname, company, jobtitle, lifecyclestage = "outreach", and a custom property (default name instantly_campaign) holding the campaign name or UUID from the Airtable row. Use upsert (not create) so existing contacts are updated in place rather than duplicated.
Step 4. Call Airtable Update Record on the original row. If Instantly accepted the lead, set the Synced checkbox to true, write the returned Instantly lead UUID into an Instantly Lead ID column, and stamp the current timestamp into a Synced At column. If Instantly skipped the lead, leave Synced unchecked and write the human-readable skip reason into the Error column so the RevOps owner can see why it didn't sync. Do not retry skipped leads automatically; the row stays in the queue with the error recorded.
Make the field names (instantly_campaign_id, custom variable columns, Synced, Error, Instantly Lead ID, Synced At) configurable at setup so users with different Airtable schemas can map their own column names without editing code. Default to the names above.
Credentials needed: Airtable (OAuth, read and write on the base), Instantly (API key v2 with leads:create and leads:read scopes), HubSpot (OAuth with crm.objects.contacts.write and crm.schemas.contacts.read so the campaign property can be validated).
Additional information
What does this prompt do?
- Watches your Airtable outbound queue and fires the moment a new row appears.
- Sends the lead into the Instantly campaign listed on the row, with first name, last name, company, title, and any custom variables you keep in Airtable.
- Creates or updates the matching contact in HubSpot keyed on email, with lifecycle stage and the campaign name set so reps can see who is in outreach.
- Marks the Airtable row as Synced with the Instantly lead ID, or writes the rejection reason back if Instantly skipped the lead.
What do I need to use this?
- An Airtable base with an outbound queue table that stores at least email, first name, last name, company, title, and the Instantly campaign you want each lead in.
- An Instantly account on the Growth plan or higher with the campaigns you want to send into already created.
- A HubSpot account where new contacts should land, with a property you want to use for the campaign name.
How can I customize it?
- Change which Airtable fields get mapped into Instantly custom variables, such as icebreaker, personalization line, or LinkedIn URL.
- Pick a different HubSpot lifecycle stage, or set a contact owner and source on the upsert.
- Decide what happens to skipped leads, for example route blocklisted or invalid addresses to a separate Airtable view for the RevOps owner to review.
Frequently asked questions
Do I need a separate row per campaign, or can one row go to multiple Instantly campaigns?
What happens if the same email is already in Instantly or HubSpot?
How fast will a new Airtable row sync?
Can I filter which Airtable rows get synced?
Does this work with HubSpot Free?
Stop hand-copying leads from Airtable into Instantly.
Connect Airtable, Instantly, and HubSpot once, and Geni keeps your outbound queue, your campaigns, and your CRM in lockstep.