Connect HubSpot
Motions reads your companies, contacts, deals, owners, notes and company lists from HubSpot through a private app that you create in your HubSpot account. Connecting takes three things: a field map in crm.yaml, a push, and the private app’s token pasted in the app.
Before you start
Section titled “Before you start”- You’re an owner or admin of the tenant: only they can save the CRM token.
- You can create a private app in HubSpot, which takes a super admin in your HubSpot account.
Connect it
Section titled “Connect it”-
Create a private app in HubSpot. In your HubSpot account, open the private apps page (Settings → Integrations → Private Apps; newer accounts list them under Development as legacy apps) and create one called “Motions”. Give it these read scopes:
Scope Motions reads crm.objects.companies.readcompanies, and the companies on a list crm.objects.contacts.readcontacts, and their companies crm.objects.deals.readdeals crm.objects.owners.readowners, by id and as a list crm.lists.readcompany lists, by name or id Create the app and keep its page open: you’ll copy its access token in step 5.
-
Write the field map.
crm.yamltells Motions which HubSpot property holds each field a step reads. Use each property’s internal name, which HubSpot shows in the property’s settings. Here’s a complete one:crm.yaml # Órbita's crm.yaml once it reads HubSpot. Only the first two lines changed: the field map already used HubSpot's property names.system: hubspotmode: read_onlycompanies:core: { tax_id: cnpj, owner_id: hubspot_owner_id }fields:segment: { from: segmento, type: enum }employees: { from: numberofemployees, type: number }contacts:core: { first_name: firstname, last_name: lastname, title: jobtitle, linkedin: hs_linkedin_url, owner_id: hubspot_owner_id }deals:core: { name: dealname, stage: dealstage, is_closed: hs_is_closed, owner_id: hubspot_owner_id }notes:core: { body: hs_note_body }coremaps the fields every motion knows (name,domain,tax_id…) to your properties. A field you don’t map is read from the property with the same name, sonameanddomainneed nothing. The field map reference lists every core field.fieldsadds your own properties under a short name and a type. Steps read them ascompany.fields.segment.- Leave
ownersout. HubSpot owners already come with a name and an e-mail.
-
Switch to HubSpot. Set
system: hubspotandmode: read_only, and deletecrm-seed.jsonif you have one: seeds are only for the test CRM, and the push refuses them for HubSpot. -
Push.
Terminal window npx motions pushThe tenant’s connection is now HubSpot, without a token yet. Until the token is set, opening a batch fails with “tenant has no hubspot credentials”.
-
Save the token in the app. Copy the private app’s access token from HubSpot. In Motions, open Settings → CRM, paste it under Private-app token, and choose Save token.
Motions checks the token with HubSpot before storing it, and shows the HubSpot account it belongs to. The token is stored encrypted and never shown again; to change it, paste a new one.
-
Check the connection. Settings → CRM now shows HubSpot, Read only and Token set. Expand Field map to see what
crm.yamlmapped, and the Lists tile shows your HubSpot company lists with their sizes.
A batch opens on a company list from HubSpot, by its name or its numeric id, or on a set of company record ids. Static and active lists both work. Lists of contacts or deals don’t.
In motion.yaml, input: { list: <name> } sets the list a batch opens on when you don’t choose one.
Keep the connection stable
Section titled “Keep the connection stable”The token belongs to the connection. A later push keeps it as long as crm.yaml still says system: hubspot. A push that switches system, back to memory for practice for instance, drops the token, and someone with the admin role has to paste it again.
An approver can push, so an approver can switch the system, but only an owner or admin can save the token again. If you need to practise on the test CRM, ask Pruma for a second tenant instead.
How Motions reads HubSpot
Section titled “How Motions reads HubSpot”- Reads are live, then kept. A step reads HubSpot when it runs, and the batch keeps what it read, so a step that runs again, after a retry or an answer, sees the same CRM. A step that waits with
ctx.waitreads fresh when it wakes. - Calls are paced. Motions keeps each tenant under HubSpot’s rate limits, so a large batch takes a while rather than failing.
- Nothing else is copied. Motions keeps what steps return as facts, and the before and after of each proposed change, but doesn’t mirror your CRM.
Motions is built by Pruma. These docs describe what the platform does today; Limitations lists what it doesn't do yet. Open the app