Sync Google Sheets leads into Bigin contacts and deals

Every 30 minutes, new rows from your lead sheet flow into Bigin as contacts (and deals when flagged), then get marked as processed.

Deterministic Code
Bigin by Zoho CRMGoogle SheetsSalesOperationsData SyncLead Enrichment
PromptCreate

Every 30 minutes, pull new lead rows from a Google Sheets intake tab and push them into Bigin as contacts, optionally creating deals for rows flagged as opportunities.

Trigger: cron, every 30 minutes.

Configurable inputs the workflow should expose: the Google Sheets spreadsheet id, the intake tab name, the A1 range to scan (default like Intake!A2:I), the column layout (first name, last name, email, phone, company, source, create-deal flag, processed marker), the Bigin Sub_Pipeline name, and the Bigin Stage name for new deals.

Step 1 — Read the sheet. Use Google Sheets Get Values on the configured range to load all rows from the intake tab. Skip the header row. For each data row, treat the processed marker column as the skip signal: if that cell already contains a value (for example "Synced" or a timestamp), skip the row. Also skip rows with an empty email, since Bigin upserts key on email.

Step 2 — Normalize each row into a Bigin contact payload. Map first name to First_Name, last name to Last_Name, email to Email, phone to Phone, company to Account_Name, and the source column to Lead_Source. Trim whitespace and drop empty fields.

Step 3 — Upsert contacts. Call Bigin Upsert Records against the Contacts module, wrapping records in the data array (max 100 per call, so batch if there are more), with duplicate_check_fields set to Email so re-runs update the existing contact instead of duplicating. After the call, iterate the per-record results and check each entry's code and status — a 200 HTTP response can still contain per-record failures like DUPLICATE_DATA, MANDATORY_NOT_FOUND, or INVALID_DATA. Capture the returned record id (details.id) for each successful upsert so we can link deals to it.

Step 4 — Create deals for flagged rows. For every row whose create-deal column is truthy ("yes", "true", checkbox true, non-empty), build a Pipelines record with Deal_Name (default to a template like "[Company] — [First name] [Last name]", falling back to the email if company is missing), Sub_Pipeline set to the configured sub-pipeline name, Stage set to the configured stage name, and Contact_Name set to the Bigin contact id from step 3. Call Bigin Insert Records against the Pipelines module. Again check per-record code/status in the response — Bigin requires Deal_Name, Sub_Pipeline, and Stage on Pipelines inserts, so surface any MANDATORY_NOT_FOUND clearly.

Step 5 — Mark processed rows in the sheet. For every row that upserted successfully (and, if applicable, whose deal insert also succeeded), write a value into the processed marker column — either a static string like "Synced" or an ISO timestamp. Use Google Sheets Update Values with valueInputOption USER_ENTERED, targeting the specific A1 cells for those rows. If any rows partially failed (contact ok, deal failed), leave the processed marker empty so the next run retries — but log the failure so the operator can see it.

Constraints and nuance: never write the processed marker for a row that had a Bigin per-record failure; the response's code field is the source of truth, not the HTTP status. Bigin request bodies always wrap records in a data array. Use the apiDomain from the Bigin credential as the base URL — do not hardcode the US domain. Respect Bigin's max of 100 records per insert/upsert call. If Bigin returns 429 (credit or concurrency exhaustion), back off and stop for this run; the next 30-minute tick will retry the unmarked rows.

Output: a run summary the operator can inspect — count of rows scanned, contacts upserted, deals created, rows skipped (already processed, missing email), and any per-record failures with their Bigin error codes.

What does this prompt do?

  • Watches a Google Sheets intake tab for new lead rows on a 30-minute schedule
  • Creates or updates each lead in Bigin as a contact, matching on email so re-runs never duplicate
  • Opens a Bigin deal in the sub-pipeline and stage you choose when a row is flagged as an opportunity
  • Marks processed rows in the sheet so the next run only picks up what's new

What do I need to use this?

  • A Google account with edit access to the lead intake spreadsheet
  • A Bigin login with permission to create contacts and deals
  • Your sheet columns lined up to first name, last name, email, phone, company, source, and a create-deal flag
  • The Bigin sub-pipeline and stage names where new deals should land

How can I customize it?

  • Change how often the sync runs (every 15 minutes, hourly, once a day)
  • Point it at a different spreadsheet, tab, or column layout
  • Set which sub-pipeline and stage new deals land in
  • Rename the create-deal flag or change how processed rows are marked (checkbox, timestamp, plain text)

FAQs

Will re-running the workflow create duplicate contacts in Bigin?
No. Contacts are matched on email address, so an existing contact gets updated instead of a new one being created. That means it's safe to run the sync as often as you like.
What happens if a row is missing an email address?
The row is skipped and left unmarked in your sheet, so it stays in the queue. Add the missing email and the next run will pick it up automatically.
Do I have to create a deal for every lead?
No. Deals only get created for rows where the create-deal column is filled in (checkbox, "yes", or any non-empty value). Everything else just becomes a Bigin contact.
Can I use this with a Bigin free plan?
Yes. Creating contacts and deals is supported on Bigin's free tier, and this workflow uses the standard contact and pipeline features.
What columns does the sheet need?
At a minimum: first name, last name, email, phone, company, source, a create-deal flag, and a column reserved for the processed marker. You can rename them however you like — just point the workflow at the right columns during setup.

Related templates

Call overdue Xero customers with an AI collections agent

Every weekday at 10am, an AI voice agent phones your most overdue Xero accounts, logs what each customer promised, and reports back to finance in Slack.

LiveKit
Xero
Deepgram
+2
Agentic Task
Local listing health board for every location you manage

See every Google Maps listing you manage on one screen, ranked worst first, with an audit button that writes the fix list for you.

Local Business Data
Google Sheets
App
Let support send one-off Loops emails without an engineer

Your team picks a template, finds the customer, checks they are safe to email, then sends it, with every send logged where the whole team can see it.

Loops.so
Stripe
Google Sheets
App
Stop cold emails to anyone with a live deal in Pipedrive

Every night at 2am, pull the contacts on your open and won deals and block them from your cold outreach before the next send goes out.

Mailshake
Pipedrive
Google Sheets
Deterministic Code
iMessage campaign console with pre-flight checks and delivery board

Build every text campaign in one screen: check who is actually reachable, see a realistic send plan, then watch delivery land row by row.

LoopMessage
Google Sheets
HubSpot
App
LinkedIn Ads budget pacing dashboard for every client account

See every LinkedIn ad account's spend against the budget you committed to, catch overspend early, and rebalance without rebuilding a spreadsheet.

LinkedIn Ads
Google Sheets
Slack Bot
App

Stop copying leads into Bigin by hand.

Let your intake spreadsheet feed Bigin contacts and deals on autopilot, without duplicates or missed rows.