Skip to main content
RapidDev - Software Development Agency
retool-integrationsRetool Native Resource

How to Integrate Retool with HubSpot

Connect Retool to HubSpot using the native HubSpot Resource in Retool's Resources tab. Authenticate with a HubSpot private app token, then build queries to search contacts, manage deals, update properties, and pull pipeline data. Retool proxies all requests server-side, so your API token never reaches the browser. Most teams have a working CRM operations panel in under 30 minutes.

What you'll learn

  • How to create a HubSpot private app token and configure the native Retool Resource
  • How to query HubSpot contacts, companies, and deals using Retool's query editor
  • How to build a CRM operations panel with editable tables and bulk property updates
  • How to chain queries so deal updates trigger data refreshes automatically
  • How to use JavaScript transformers to flatten nested HubSpot property objects
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read25 minutesMarketingLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to HubSpot using the native HubSpot Resource in Retool's Resources tab. Authenticate with a HubSpot private app token, then build queries to search contacts, manage deals, update properties, and pull pipeline data. Retool proxies all requests server-side, so your API token never reaches the browser. Most teams have a working CRM operations panel in under 30 minutes.

Quick facts about this guide
FactValue
ToolHubSpot
CategoryMarketing
MethodRetool Native Resource
DifficultyIntermediate
Time required25 minutes
Last updatedApril 2026

Why connect Retool to HubSpot?

HubSpot's native UI is optimized for individual sales reps working through their daily pipeline. It is not designed for operations teams who need to bulk-edit hundreds of contact properties, run cross-object reports, or build custom approval workflows that combine HubSpot data with internal databases. Retool solves this by giving you direct access to HubSpot's CRM API through a visual query builder — no custom code required for most workflows.

The most common Retool-HubSpot use case is a CRM operations panel where sales ops teams can search contacts using multiple filter criteria simultaneously, batch-update lifecycle stages or owner assignments, view deal pipeline stages across all reps, and export enriched contact lists that combine HubSpot data with revenue data from a connected PostgreSQL database. These workflows are impossible or extremely slow in HubSpot's native interface but straightforward to build in Retool.

Retool's native HubSpot connector supports all major CRM objects: contacts, companies, deals, tickets, line items, and custom objects. You can read, create, update, and associate records, and the connector exposes HubSpot's search API so you can build filter UIs backed by real server-side search rather than loading all records into the browser.

Integration method

Retool Native Resource

Retool includes a native HubSpot connector that handles authentication and provides pre-built action types for contacts, companies, deals, tickets, and properties. You configure it once in the Resources tab using a HubSpot private app token or OAuth 2.0, and all subsequent queries route through Retool's server-side proxy. This eliminates CORS concerns and keeps your API credentials off the client entirely.

Prerequisites

  • A HubSpot account with CRM access (any plan, including free)
  • Permission to create private apps in HubSpot (requires Super Admin or a role with App Marketplace access)
  • A Retool account (Cloud or self-hosted) with Resource creation permissions
  • Basic familiarity with Retool's query editor and Table component
  • Knowledge of which HubSpot CRM objects and properties you need to access

Step-by-step guide

1

Create a HubSpot private app and copy the access token

Navigate to your HubSpot account and go to Settings (gear icon, top right) → Integrations → Private Apps. Click Create a private app. Give it a descriptive name like Retool CRM Integration. On the Scopes tab, select the CRM scopes your Retool app needs — at minimum, enable crm.objects.contacts.read and crm.objects.contacts.write for contact management, crm.objects.deals.read and crm.objects.deals.write for deals, and crm.objects.companies.read for company lookups. If you plan to manage owners or pipelines, also add crm.objects.owners.read and crm.pipelines.orders.read. Click Create app, then confirm the creation. HubSpot generates an access token displayed once — copy it immediately and store it securely. This private app token is scoped to exactly the permissions you granted, which is more secure than using a full API key. Unlike OAuth, private app tokens do not expire unless you rotate them manually, making them well-suited for server-to-server integrations like Retool. Note the token value; you will paste it into Retool in the next step.

Pro tip: Scope your private app to the minimum necessary CRM objects. You can always edit the private app later to add scopes if you expand your Retool app's functionality.

Expected result: You have a HubSpot private app access token (a long string beginning with pat-) copied to your clipboard or a secure location.

2

Add the HubSpot Resource in Retool

In Retool, click the Resources tab in the left navigation (or navigate to retool.com/resources). Click the Add Resource button in the top right corner. In the resource type picker, scroll to or search for HubSpot — it appears under the CRM category with the HubSpot logo. Click HubSpot to open the configuration panel. Give the resource a clear name like HubSpot CRM or HubSpot Production. In the Authentication section, select Private app token as the authentication method. Paste your private app access token into the Access token field. Retool stores this token encrypted on its servers; it is never sent to the browser. If your organization uses multiple HubSpot portals (e.g., separate portals for different regions), create one Resource per portal using descriptive names. If your organization uses OAuth 2.0 instead of private app tokens — for example, if end users should authenticate with their own HubSpot accounts — select OAuth 2.0 from the authentication dropdown. You will need to provide a Client ID and Client Secret from a HubSpot app created in your developer account, along with the redirect URL shown in Retool. Click Save. Retool will test the connection and confirm the resource is functional. You should see a green Connected status indicator.

Pro tip: If you use Retool's resource environments (production, staging), you can configure separate HubSpot portals or tokens per environment so staging Retool apps never write to your production CRM data.

Expected result: The HubSpot resource appears in your Resources list with a Connected status. You can now create queries targeting this resource.

3

Write your first HubSpot query to fetch contacts

Open or create a Retool app. In the Code panel at the bottom, click the + button to create a new query. Select your HubSpot resource from the Resource dropdown. The query editor switches to HubSpot mode, showing an Action dropdown. Select Search contacts from the action list to access HubSpot's CRM search API, which supports complex filter conditions and returns paginated results. In the Filter conditions section, you can leave it empty to return all contacts or add a filter — for example, set property to lifecyclestage, operator to is equal to, and value to lead to find all lead-stage contacts. In the Properties to return field, add the contact properties you want: firstname, lastname, email, phone, lifecyclestage, hubspot_owner_id, company, and hs_lead_status are common starting points. Set the limit to 100 (HubSpot's maximum per page). Enable the Paginate automatically toggle if you want Retool to handle pagination. Run the query. The response is a JSON object with a results array containing contact objects, each with an id and a properties object. Use a transformer to flatten this structure — click the Advanced tab on the query, enable Transform results, and write a JavaScript function that maps the results array into a flat array of objects for easy binding to a Table component.

contacts_transformer.js
1// Query transformer — paste into Advanced → Transform results
2const results = data.results || [];
3return results.map(contact => ({
4 id: contact.id,
5 first_name: contact.properties.firstname || '',
6 last_name: contact.properties.lastname || '',
7 email: contact.properties.email || '',
8 phone: contact.properties.phone || '',
9 lifecycle_stage: contact.properties.lifecyclestage || '',
10 owner_id: contact.properties.hubspot_owner_id || '',
11 company: contact.properties.company || '',
12 created_at: contact.properties.createdate
13 ? new Date(contact.properties.createdate).toLocaleDateString()
14 : ''
15}));

Pro tip: HubSpot returns all dates as Unix millisecond timestamps. The transformer above converts createdate to a human-readable date. Apply the same pattern to any date property.

Expected result: The query returns a flat array of contact objects. In the query response inspector, you can see each contact as a row with named properties. The data is ready to bind to a Table component.

4

Build a contacts table with inline editing and update capability

In the Retool canvas, drag a Table component from the Component panel onto the canvas. In the Table's data source field, type {{ searchContacts.data }} (replacing searchContacts with whatever you named your contacts query). The table populates with your contact data, with each property as a column. Configure which columns are visible using the Columns section in the Table's right panel — hide the id column from display but keep it available for queries. Enable Editable for the lifecycle_stage and owner columns by toggling the Editable switch on those column configurations. This allows users to directly edit values in the table. Add a Button component to the canvas labeled Save Changes. In the button's onClick event handler, create a new query. Set it to action Update contact in HubSpot, set the Contact ID to {{ table1.selectedRow.id }}, and in the Properties section add the fields you want to update. However, for bulk updates across multiple rows, a better pattern is to check table1.changesetArray — Retool's built-in property that tracks all edited rows — and loop through them. Create a JavaScript query that iterates over the changeset and calls individual update queries per row. Connect the Save button's onClick event to this JavaScript query. Add a success notification in the query's On success event handler to confirm updates to the user.

bulk_update.js
1// JavaScript query to bulk-update changed contacts
2// Reference this in the Save button's onClick event
3const changes = table1.changesetArray;
4if (!changes || changes.length === 0) {
5 return 'No changes to save';
6}
7
8const updatePromises = changes.map(row => {
9 return updateContact.trigger({
10 additionalScope: {
11 contactId: row.id,
12 properties: {
13 lifecyclestage: row.lifecycle_stage,
14 hubspot_owner_id: row.owner_id
15 }
16 }
17 });
18});
19
20await Promise.all(updatePromises);
21await searchContacts.trigger();
22return `Updated ${changes.length} contacts`;

Pro tip: table1.changesetArray only tracks rows the user has actually edited. Running it before any changes returns an empty array, so your Save button will do nothing until a user modifies a cell.

Expected result: Users can edit lifecycle stage and owner values directly in the table. Clicking Save Changes updates all modified contacts in HubSpot and refreshes the table with the latest data.

5

Add deal pipeline queries and a pipeline view

Create a second query in the Code panel, again targeting your HubSpot resource. Select Search deals from the Action dropdown. In the Properties to return field, add: dealname, dealstage, closedate, amount, hubspot_owner_id, and pipeline. Add a Filter condition to limit results — for example, filter by closedate is greater than today's timestamp minus 90 days to focus on active deals. Write a transformer similar to the contacts transformer to flatten the deals response. Drag a second Table component onto the canvas for deals. Bind it to the deals query using {{ getDeals.data }}. Configure columns to display deal name, stage, close date, amount (formatted as currency using Retool's column formatting), and assigned owner. Add a Select component above the deals table with options for each pipeline stage (you can query HubSpot's pipelines endpoint to populate these dynamically). Set the deals query's filter value to {{ pipelineFilter.value }} so the table responds to the dropdown. This gives sales managers a live pipeline view filtered by stage. Arrange both tables in a Container component with tabs: one tab for Contacts, one for Deals, so the panel feels like a unified CRM tool rather than two separate tables.

deals_transformer.js
1// Deals transformer — paste into Advanced → Transform results
2const results = data.results || [];
3return results.map(deal => ({
4 id: deal.id,
5 deal_name: deal.properties.dealname || 'Untitled Deal',
6 stage: deal.properties.dealstage || '',
7 pipeline: deal.properties.pipeline || '',
8 close_date: deal.properties.closedate
9 ? new Date(parseInt(deal.properties.closedate)).toLocaleDateString()
10 : 'No date',
11 amount: deal.properties.amount
12 ? `$${parseFloat(deal.properties.amount).toLocaleString()}`
13 : '$0',
14 owner_id: deal.properties.hubspot_owner_id || ''
15}));

Pro tip: HubSpot deal stages are internal string identifiers like appointmentscheduled or qualifiedtobuy. Pull the pipelines endpoint to get human-readable stage labels and map them in your transformer.

Expected result: A functional deals pipeline view displays in the second table, filterable by stage. Both the contacts and deals tables are accessible via a tabbed container.

6

Configure event handlers for seamless UX

Polish the CRM panel by wiring up event handlers that keep the UI responsive. Select the Table component for contacts. In the Table's Event handlers section, add a Row selection event handler that triggers a second getContactDetail query using {{ table1.selectedRow.id }} as the contact ID. This allows a side panel or drawer to show full contact details when a row is clicked. For the Save Changes button, configure the On success event handler of the bulk update query to trigger the searchContacts query (to refresh data) and show a notification component with the message 'Contacts updated successfully'. Add error handling by configuring the On failure event handler to display an error notification showing {{ error.message }}. Consider adding a Retool Workflow for any automation that should run outside the UI — for example, a scheduled workflow that pulls overnight changes from HubSpot and syncs them to a connected database. For complex multi-step operations like creating a deal with associated contacts in one transaction, Retool Workflows with a Webhook trigger provide better error handling and retry logic than chaining queries in the app layer. For teams building complex CRM automation combining multiple HubSpot objects, custom transformers, and scheduled syncs, RapidDev's team can help architect the full Retool solution.

Pro tip: Use Retool's Confirm action in the event handler for destructive operations like deleting contacts. A confirmation modal prevents accidental data loss.

Expected result: The CRM panel has smooth interactions: clicking a row shows contact details, saving changes refreshes the table, and errors display as readable notifications rather than raw error objects.

Common use cases

Build a sales ops bulk contact editor

Create a Retool panel where sales ops can search contacts by any combination of properties — lifecycle stage, owner, company, last activity date — and bulk-update them in one action. The Table component shows editable cells for owner and lifecycle stage, and a Save button triggers batch update queries using HubSpot's batch contacts API.

Retool Prompt

Build a Retool app that lets users search HubSpot contacts by lifecycle stage and owner, display results in an editable table showing contact name, email, company, owner, and lifecycle stage, and include a Save Changes button that batch-updates modified rows using the HubSpot Contacts API.

Copy this prompt to try it in Retool

Deal pipeline visibility dashboard

Pull all open deals across every rep and pipeline stage into a Retool Table with filters for owner, stage, close date, and deal value. Sales managers can click any deal to open a detail panel showing associated contacts and recent activity, then update the deal stage directly from Retool without switching back to HubSpot.

Retool Prompt

Build a Retool dashboard that shows all open HubSpot deals in a Table component with columns for deal name, owner, pipeline stage, close date, and amount. Add filter dropdowns for owner and stage. When a row is selected, show a detail panel with the deal's associated contacts and a dropdown to update the deal stage.

Copy this prompt to try it in Retool

Cross-platform customer operations panel

Combine HubSpot contact data with a PostgreSQL orders database to give support and ops teams a unified customer view. A single Retool search bar queries both systems simultaneously — HubSpot for CRM history and the database for order history — and displays a merged timeline showing deal activity alongside purchase records.

Retool Prompt

Build a Retool customer lookup tool that queries both HubSpot contacts API and a PostgreSQL orders table using a shared customer email input. Show HubSpot deal history and database order history side by side in two Table components on the same page.

Copy this prompt to try it in Retool

Troubleshooting

Query returns 401 Unauthorized error

Cause: The private app token has been deleted or rotated in HubSpot, or the token was pasted incorrectly into the Retool Resource configuration.

Solution: Go to HubSpot Settings → Integrations → Private Apps and confirm the private app still exists and is active. If the token was rotated, copy the new token and update it in Retool's Resources tab by editing the HubSpot resource. Verify there are no leading or trailing spaces in the token field.

Query returns 403 Forbidden — MISSING_SCOPES error

Cause: The private app token does not have the CRM scope required for the operation you are attempting. For example, trying to read deals when only contact scopes were granted.

Solution: In HubSpot, go to Settings → Integrations → Private Apps → click your private app → Scopes tab. Add the missing scope (e.g., crm.objects.deals.read) and save. HubSpot regenerates the access token when you update scopes, so copy the new token and update the Retool Resource configuration.

Search query returns an empty results array even when contacts exist

Cause: HubSpot's search API requires properties to be explicitly requested. If the Properties to return field is empty, HubSpot returns contacts with no properties, making records appear empty.

Solution: In the query editor's Properties to return field, explicitly list every property you need: firstname, lastname, email, lifecyclestage, etc. HubSpot does not return all properties by default — you must specify them. The email property is required for most contact searches.

Table transformer crashes with 'Cannot read property of undefined' error

Cause: Some HubSpot contacts have null or missing property values, and the transformer attempts to access nested properties without null checks.

Solution: Use the || '' fallback pattern for all property accesses in your transformer function. Every contact.properties.X should be written as contact.properties.X || '' to return an empty string when the property is missing rather than crashing.

typescript
1// Safe property access pattern for transformer
2return data.results.map(contact => ({
3 email: contact.properties?.email || '',
4 firstname: contact.properties?.firstname || '',
5 lifecyclestage: contact.properties?.lifecyclestage || 'unknown'
6}));

Best practices

  • Use HubSpot private app tokens instead of legacy API keys — private apps can be scoped to specific CRM objects and revoked independently without affecting other integrations.
  • Store the private app token in a Retool configuration variable marked as secret (Settings → Configuration Variables) rather than hardcoding it into a resource — this makes credential rotation easier.
  • Enable query caching (5-30 seconds) on high-frequency read queries like contact searches to reduce HubSpot API usage, since HubSpot enforces rate limits (100 requests per 10 seconds on most plans).
  • Use GUI mode for write operations (create contact, update deal) rather than raw API calls — Retool's GUI mode validates inputs before sending and reduces accidental data corruption.
  • Use table1.changesetArray rather than the selected row for bulk updates — it tracks all modified rows in one operation and enables batch updates that respect HubSpot's bulk API endpoints.
  • Flatten nested HubSpot property objects with a query transformer before binding to Table components — raw HubSpot responses have a nested properties object that confuses Retool's column auto-detection.
  • For scheduled syncs or webhook-triggered workflows (like syncing HubSpot deal updates to a database nightly), use Retool Workflows instead of app-layer queries — Workflows have retry logic, error handlers, and run without a user session.
  • Test write operations against a HubSpot sandbox portal (available on paid plans) before running them against production CRM data — accidental bulk updates to contacts are difficult to reverse.

Alternatives

Frequently asked questions

Does Retool support HubSpot OAuth 2.0 in addition to private app tokens?

Yes. When creating the HubSpot Resource in Retool, you can select OAuth 2.0 as the authentication method. You will need a HubSpot developer app with a Client ID and Client Secret. OAuth is preferable when end users should authenticate with their own HubSpot accounts rather than sharing a single service token. Private app tokens are simpler for team-internal tools where one set of credentials is acceptable.

Can I connect Retool to multiple HubSpot portals?

Yes. Create one HubSpot Resource per portal in Retool's Resources tab, giving each a descriptive name like HubSpot - North America or HubSpot - EMEA. Each resource has its own private app token. Within a single Retool app, you can run queries against different HubSpot resources to compare data across portals or manage a multi-portal operation from one dashboard.

Will Retool's HubSpot integration work with custom CRM objects?

Yes. HubSpot custom objects are accessible through HubSpot's CRM Objects API. In Retool, use the Search CRM objects action and specify your custom object type ID in the query configuration. You can read, create, update, and associate custom object records the same way you work with standard contacts and deals.

How do I handle HubSpot's rate limits in Retool?

HubSpot allows 100 API requests per 10 seconds on most plans. Enable query caching in Retool (Advanced tab → Cache settings) for read queries that run frequently. For bulk operations that could exceed rate limits, use Retool Workflows with a Loop block set to sequential execution and add a small delay between iterations. HubSpot also offers a batch contacts update endpoint that counts as a single API call for up to 100 contacts.

Can I trigger HubSpot workflows from Retool?

You can call HubSpot's Engagements API to log activities (calls, emails, meetings) that trigger HubSpot internal workflows, and you can directly update contact properties that serve as HubSpot workflow enrollment triggers. However, you cannot directly call a HubSpot workflow by ID from the API — you must trigger them indirectly by creating the condition that enrolls a contact in that workflow.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.