Every 15 minutes
Start an Airtable onboarding record when a HubSpot deal is won
When a deal is won, an onboarding record is created in your Airtable tracker and the contact becomes a Customer in HubSpot.
- Runs
- Every 15 minutes
- Apps
- Airtable, HubSpot
- AI
- Not needed
- Access
- crm.objects.deals.read, crm.objects.contacts.write; Airtable write
Send this to your assistant
Create a ClickRuntime automation: when a HubSpot deal moves to Closed Won, create an onboarding record in my Airtable 'Onboarding' table and set the contact's lifecycle stage to Customer.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
A services firm or agency runs client onboarding from an Airtable base: kickoff date, account lead, checklist and status. Sales closes the deal in HubSpot, then sends a message asking someone to set up the onboarding record, and the contact's lifecycle stage in HubSpot is never updated, so marketing keeps emailing them as a prospect.
This handles both sides at the moment of the win. A new record appears in the onboarding tracker with the client's details, and HubSpot marks the contact as a customer, so the delivery team can start and marketing stops treating them as a lead.
What you get out of it
Onboarding starts without a handover message
The record is there for the delivery team as soon as the deal closes.
HubSpot stays accurate
Contacts become Customers in HubSpot, so lists and reports are right and prospect emails stop.
Every won deal is caught once
Deals already handled are remembered, so no client gets two onboarding records.
You get a short summary
An email tells you which clients were set up, so you can check nothing's missing.
How it works
What happens, step by step
Every 15 minutes, ClickRuntime checks HubSpot for deals newly moved to Closed Won.
It skips deals it has already set up, so each client is handled once.
It creates an onboarding record in your Airtable table with the client and deal details.
It sets the deal's contacts to Customer in HubSpot and emails you a short summary.
Before it runs live
- Connect Airtable
- Connect HubSpot
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Act only on the items that match your own rules, and skip the rest
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Airtable and HubSpot steps into one automation
Under the hood
The code that runs this automation
import time
from clickruntime import on_trigger, credentials, http, state, notify, report_fetched
BASE_ID = "appXXXXXXXXXXXXXX"
def hs(method, path, **kw):
r = http.request(method, f"https://api.hubapi.com{path}", headers={"Authorization": f"Bearer {credentials.connection('hubspot', 'work')}"}, **kw)
return r.raise_for_status() or (r.json() if r.content else {})
def at(method, path="", **kw):
r = http.request(method, f"https://api.airtable.com/v0/{BASE_ID}/{path}", headers={"Authorization": f"Bearer {credentials.connection('airtable', 'work')}"}, **kw)
return r.raise_for_status() or r.json()
@on_trigger
def run(event):
since = str(state.get("since") or int((time.time() - 86400) * 1000))
deals = hs("POST", "/crm/v3/objects/deals/search", json={"filterGroups": [{"filters": [{"propertyName": "dealstage", "operator": "EQ", "value": "closedwon"},
{"propertyName": "hs_lastmodifieddate", "operator": "GTE", "value": since}]}], "properties": ["dealname", "amount"], "limit": 50})["results"]
done = set(state.get("done") or []); deals = [d for d in deals if d["id"] not in done]
report_fetched(len(deals))
if not deals:
return {"onboarded": 0}
for d in deals:
p, links = d["properties"], hs("GET", f"/crm/v4/objects/deals/{d['id']}/associations/contacts").get("results", [])
c = hs("GET", f"/crm/v3/objects/contacts/{links[0]['toObjectId']}?properties=email,firstname,lastname")["properties"] if links else {}
at("POST", "Onboarding", json={"typecast": True, "records": [{"fields": {"Client": p["dealname"], "Amount": float(p.get("amount") or 0),
"Contact": f"{c.get('firstname') or ''} {c.get('lastname') or ''}".strip(), "Email": c.get("email", ""), "Status": "Not started"}}]})
for link in links:
hs("PATCH", f"/crm/v3/objects/contacts/{link['toObjectId']}", json={"properties": {"lifecyclestage": "customer"}})
done.add(d["id"])
state.set("done", list(done)[-1000:]); state.set("since", int(time.time() * 1000) - 3600000)
notify.email_me(f"{len(deals)} new clients set up for onboarding", "\n".join(d["properties"]["dealname"] for d in deals))
return {"onboarded": len(deals)}FAQ
Common questions
What goes into the Airtable record?
Which contact is updated in HubSpot?
How quickly does the record appear?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Turn people in your Airtable engagement table into HubSpot contacts
People added to your Airtable engagement table, such as those who comment on your LinkedIn posts, become HubSpot contacts and are marked as synced.
See how it worksCopy new HubSpot deals into Airtable
Every new HubSpot deal appears in your Airtable Deals table within 15 minutes, with a heads-up in Slack.
See how it worksKeep contacts in sync between Airtable and HubSpot
Contacts stay the same in Airtable and HubSpot whichever side you edit, with the most recent change winning.
See how it worksKeep exploring
Set up “Start an Airtable onboarding record when a HubSpot deal is won” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.