Skip to content
SolutionArg

Integrations

Integrating HubSpot with Your ERP: Lessons from a 50,000-Product Catalog

Lessons from connecting a 50,000+ product Sage Intacct catalogue to HubSpot: connector vs custom, rate limits, search caps, upserts and fast search.

By SolutionArg7 min read

TL;DR

  • Start with the pre-built connector if one exists. Sage, for example, offers Sage Intacct Data Flow with a pre-built, two-way HubSpot integration (Sage).
  • Go custom when you need something the connector doesn't give you. In my case: a fast, real-time search over 50,000+ Sage Intacct products with dynamic filters, on a HubSpot-hosted website.
  • Large catalogues hit HubSpot's limits fast. CRM search returns at most 10,000 results per query and allows 5 requests per second (HubSpot). Batch endpoints take 100 inputs per request (HubSpot).
  • Treat the ERP as the source of truth for products and prices. Sync only what sales uses, and key everything on the ERP's ID.

The situation

A client had a large product database (50,000+ items) in Sage Intacct. They wanted visitors to search it quickly and dynamically, directly on the front end of their HubSpot website.

I built serverless functions that manage all the API requests securely. They power a custom HubSpot module with a real-time search bar and dynamic filters that adapt automatically to what the user types.

That project shaped the lessons below. They apply to any large-catalogue ERP integration, whether the catalogue is shown on your website, on CRM records or both.

Decision 1 — Connector or custom?

Ask three questions:

  1. Does a maintained connector exist for your ERP? Sage Intacct Data Flow advertises a pre-built HubSpot integration that syncs "both ways to and from HubSpot CRM and Sage Intacct", aimed at quote-to-cash and invoicing (Sage).
  2. Does it cover the experience you need? A connector moves data. It doesn't necessarily give website visitors or reps a fast, filtered search.
  3. Who maintains it? A vendor-maintained connector costs less to own than custom code.

If the connector covers your use case, use it. Custom work is for the gap.

Decision 2 — What should live in HubSpot?

Not every ERP field belongs in the CRM. For each product field, ask: will sales filter, quote or report on this? If not, leave it in the ERP and fetch it on demand.

For the fields you do sync:

  • Store the ERP item ID in a HubSpot property marked as a unique identifier.
  • Sync prices if reps quote from HubSpot. Products support standard and tiered pricing properties such as hs_tier_ranges and hs_tier_prices (HubSpot Products API).
  • Sync status (active or discontinued) so reps never quote dead items.

Decision 3 — How to keep it in sync

Initial load

For the first import of tens of thousands of rows, HubSpot's imports API is designed for files. It supports CSV and spreadsheet formats and maps columns to properties by internal name (HubSpot Imports API).

Ongoing changes

Use batch upsert keyed on your unique ID. Records that exist are updated; new ones are created. HubSpot documents a dedicated products endpoint for this (HubSpot — batch upsert products).

POST /crm/objects/2026-09/products/batch/upsert

The idProperty you pass must be a property marked as a unique identifier (HubSpot custom objects guide — upsert).

Do the maths on rate limits

HubSpot's limits for privately distributed apps (HubSpot usage guidelines):

TierBurst (per app)Daily (per account)
Free / Starter100 requests / 10 s250,000
Professional190 requests / 10 s625,000
Enterprise190 requests / 10 s1,000,000

At 100 records per batch call, 50,000 products take 500 calls. That's comfortable if you batch, and painful if you update one product per call. When you exceed a limit, HubSpot returns 429. The X-HubSpot-RateLimit-* headers tell you how much room you have, except on search responses, which don't include them.

Decision 4 — Search: where should the query run?

This decision saves the most time. You have two broad choices.

If you've synced the catalogue into HubSpot products, the CRM search endpoints (source):

  • are limited to five requests per second per account;
  • return up to 200 records per page;
  • cap any query at 10,000 total results, and paging beyond that returns a 400 error;
  • allow five filter groups, six filters per group and 18 filters in total.

With 50,000 products, a broad query ("all pumps") can exceed 10,000 results, and a public search box with several visitors typing will exceed five requests per second. The CRM search API isn't built to be a public, high-traffic catalogue search.

B. Query the source (or your own index) through a server-side layer

Keep the catalogue where it lives, or in a search index you control, and put a thin server-side layer between the page and the data. That layer holds credentials, validates input and returns only what the page needs. That's the role serverless functions played in my Sage Intacct project.

Whichever you choose:

  1. Debounce input. Wait until the user pauses typing.
  2. Filter early. Category or brand filters shrink result sets dramatically.
  3. Return small pages. Twenty good matches, not ten thousand.
  4. Never expose ERP or HubSpot credentials in the browser.

Hosting the server-side layer

OptionRequirement / limits
HubSpot CMS serverless functions (for website modules)Content Hub Enterprise. 10 s per execution, 600 execution-seconds per minute per account, 6 MB payload, 100 endpoints per account (HubSpot Developers)
App serverless functions (behind CRM app cards)Installing the app requires Enterprise; 15-second timeout (HubSpot Developers)
Your own backendAny host. From an app card, call it with hubspot.fetch(): allow-listed URLs, 15 s default timeout (120 s max), 1 MB payloads (HubSpot Developers)

The 10-second CMS limit is a good discipline: if a search takes longer than that, it's too slow for users anyway.

Decision 5 — The ERP side

Each ERP has its own API style and limits; read them before estimating. For Sage Intacct:

  • The developer site documents the XML Web Services API and labels it "XML API (Legacy)".
  • Sage says its developer documentation is moving to developer.sage.com/intacct with the FY27 R1 release, and that existing XML integrations will keep working (Sage Intacct Developer).

A checklist for your own ERP project

  • Check for a maintained connector and list what it doesn't cover.
  • Choose the 10–20 product fields sales really uses.
  • Add a unique ERP ID property and use upserts.
  • Plan the initial import separately from ongoing sync.
  • Calculate API calls per sync run against your tier's limits.
  • Decide where search runs: CRM search (10,000-result cap, 5 req/s) or the source/index behind a server-side layer.
  • Pick hosting: CMS serverless (Content Hub Enterprise), app serverless (Enterprise) or your own backend.
  • Log every sync run and alert on failures.

Sources

FAQ

Is there a native Sage Intacct–HubSpot integration? Sage offers Sage Intacct Data Flow, which it describes as a pre-built, two-way integration with HubSpot.

Can HubSpot's CRM search power a 50,000-product website search? It isn't a good fit. Any single CRM search query returns at most 10,000 results and is limited to five requests per second per account. Query the source or a dedicated index through a server-side layer instead.

How many records can I update per API call? HubSpot's object batch endpoints accept up to 100 inputs per request.

Do I need Enterprise for a catalogue search? For HubSpot-hosted serverless functions, yes: CMS serverless needs Content Hub Enterprise, and app serverless needs Enterprise to install. Your own backend avoids that requirement.

Let's find the manual work hiding in your HubSpot.

30 minutes. You show me how things work today; I'll tell you what I'd fix first and roughly what it takes — no pitch deck.

Almost always reply within 24 hours