Skip to content

Use Supabase as Your HubSpot API Layer (Stop Calling the HubSpot API)

A developer pattern for teams tired of the HubSpot API: point your app at Supabase, query and write with plain SQL, and let a real-time two-way sync keep HubSpot mirrored underneath. Covers what direct HubSpot API access actually costs, how the read/write layer works, and when the pattern fits.

Author
Ruben Burdin · Founder & CEO
Published
July 20, 2026
Read time
5 min read
Use Supabase as Your HubSpot API Layer (Stop Calling the HubSpot API)
DATA ENGINEERING

Every internal tool that touches HubSpot starts the same way: someone wires up the HubSpot API. Then comes OAuth and token refresh, per-app rate limits, pagination, the search endpoint's quirks, the associations API, batch endpoints, and retry logic, reimplemented in every service that needs a contact or a deal. The feature you actually wanted, a dashboard or an admin panel, is buried under CRM plumbing.

There is a cleaner pattern that teams keep arriving at: point your application at Supabase, not at HubSpot. Your code reads and writes plain Postgres, and a real-time two-way sync keeps HubSpot mirrored underneath. Developers write SQL; the sync deals with HubSpot. This post explains what direct HubSpot API access really costs, how the read/write layer works, and where the pattern fits.

Supabase as your HubSpot API layer: plain SQL reads, write once, no HubSpot API in your code, real-time both ways

What talking to the HubSpot API directly actually costs

The HubSpot API is not hard because any one call is hard. It is hard because a real application has to handle all of it, everywhere, forever:

  • OAuth and token refresh in every service that reads or writes HubSpot.
  • Rate limits, both burst and daily, shared across everything your app does.
  • Pagination and the search endpoint's own rules for filtering and cursors.
  • The associations API for anything relational, like a contact's company or a deal's line items.
  • Batch endpoints and their size limits when you move more than a handful of records.
  • Retries, backoff, and idempotency so a transient failure does not double-write.
  • Schema drift when a property is added or a type changes on the HubSpot side.

None of this is business logic. It is the tax you pay to get a record in and out of HubSpot, and every new service pays it again. Multiply it across a few dashboards, an internal admin tool, and a couple of background jobs, and a meaningful share of engineering time goes to CRM plumbing rather than product.

The pattern: Supabase as your HubSpot read/write layer

The idea is to give your application one place to talk to, and make that place a database. HubSpot data lives in Supabase as normal Postgres tables. Your app reads and writes those tables with plain SQL, Supabase auth, and row-level security. A real-time two-way sync sits between Supabase and HubSpot: a change in HubSpot lands in Supabase within seconds, and a write to Supabase is pushed back into HubSpot with the field mapping you configured.

The result is that your code never imports a HubSpot SDK. Fetching a contact is a query. Updating a deal is an update statement. The rate limits, pagination, and associations are handled once, by the sync, instead of in every service you write.

sql
-- Instead of paging the HubSpot search API in app code,
-- read the synced Supabase table with plain SQL:
select c.email, c.lifecyclestage, co.name as company
from contacts c
join companies co on co.id = c.associated_company_id
where c.lifecyclestage = 'customer';

-- And instead of a HubSpot batch-update call,
-- write to Supabase; the sync pushes it to HubSpot:
update contacts set lifecyclestage = 'opportunity'
where email = 'lead@example.com';

Reads no longer touch HubSpot at all, and writes go through one managed path instead of scattered API calls.

Three-layer architecture: your code reads and writes Supabase, Supabase holds the Postgres tables you own, and Stacksync keeps HubSpot mirrored
Your code talks to Supabase; Stacksync keeps HubSpot mirrored underneath.

Direct HubSpot API vs Supabase as the layer

The two approaches diverge on almost every axis a developer cares about.

ConcernCalling the HubSpot API directlySupabase as the layer
Auth in your codeOAuth and token refresh per serviceSupabase keys, handled once
ReadsRate-limited API calls and paginationPlain SQL against Postgres
Joins across objectsAssociations API, stitched in codeSQL joins on synced tables
Rate limitsShared burst and daily quotaNo HubSpot limit on reads; batched writes
WritesBatch endpoints and retry logicWrite to Supabase, sync pushes to HubSpot
Local developmentLive HubSpot or hand-rolled mocksA real Postgres database

Where the HubSpot API tax lands, and how a Supabase layer removes it from your app.

Reads and writes both work, not just a read cache

It is worth being precise, because a lot of teams have been burned by a one-way export that turns stale. This is not a read replica. Because the sync is two-way, writing to a synced Supabase table updates the matching HubSpot record in real time. You can build an internal admin tool where an operator edits a value in your own UI, the write goes to Supabase, and HubSpot reflects it moments later, all fields tied together, changes on either side flowing to the other.

HubSpot still validates those writes, so a value it refuses is rejected. The difference in this pattern is that the rejection surfaces at the sync layer where you can see and fix it, rather than failing silently inside your application. The details of that, plus how a string in HubSpot becomes an integer in Supabase, are covered in the field mapping and data-type guide.

Topology: your application reads and writes Supabase over SQL, Stacksync change data capture syncs two-way with HubSpot over batched API calls
Reads hit Postgres; writes flow to HubSpot through one managed sync.
Book a Stacksync demo: build on Supabase with plain SQL while the sync keeps HubSpot mirrored

When this pattern fits, and when it doesn't

It fits cleanly when your application is the thing that needs HubSpot data:

  • Dashboards and reporting that join HubSpot data with your product's own tables.
  • Internal admin tools and back-office apps that read and update CRM records.
  • Customer-facing app backends that need live account or contact data.
  • Background jobs that would otherwise hammer the HubSpot API on a schedule.

It is not a replacement for HubSpot. Your go-to-market team still lives in HubSpot's interface, workflows, and reporting. The pattern removes the HubSpot API from your code; it does not remove HubSpot. If you are building internal tools on Supabase more broadly, the enterprise internal-tools playbook covers the wider architecture, and this post is the HubSpot-specific slice of it: the part where Supabase stands in for the HubSpot API.

Bringing it together

The HubSpot API is fine for a one-off script and painful as the foundation of every internal tool you build. Putting Supabase in front of it flips the model: your code reads and writes a database, a real-time two-way sync keeps HubSpot and Supabase as one live dataset, and the rate limits, pagination, and associations become someone else's problem.

If you are choosing an approach, compare it against HubSpot's native Data Sync, and if you handle regulated data see how to keep the sync HIPAA-compliant. To stand up the sync behind your tools on real data, see the HubSpot and Supabase integration or book a demo.

Start syncing with Stacksync: point your app at Supabase and stop calling the HubSpot API

FAQ

Frequently asked questions

Can Supabase replace my direct HubSpot API calls?
For reading and writing CRM data from your own code, yes. You point your app at Supabase and work in plain SQL, while a real-time two-way sync keeps HubSpot mirrored underneath. A read hits Supabase instead of the HubSpot API, and a write to Supabase is pushed into HubSpot by the sync. You still use HubSpot itself for its CRM interface and automation; what changes is that your services stop making HubSpot API calls.
How do I build a dashboard or internal tool on HubSpot data without using the HubSpot API?
Sync HubSpot into Supabase and build the tool against Supabase. Your dashboard runs normal SQL queries and joins over Postgres tables, with Supabase auth and row-level security, and never handles HubSpot OAuth, pagination, or rate limits. The sync keeps the Supabase copy current in real time, so the dashboard reflects live HubSpot data without any API code in your app.
If I write to Supabase, does it update HubSpot automatically?
Yes, when the sync is two-way. A write to a synced Supabase table is captured and applied to the matching HubSpot record in real time, with the field mapping and type conversions you configured. HubSpot validates the write and, if it rejects one, the sync surfaces it so you can correct the value rather than silently losing it. Your app just writes to the database; the sync handles the HubSpot side.
Does using Supabase as a layer help with HubSpot API rate limits?
Yes. When every service calls HubSpot directly, they compete for the same API quota and hit burst and daily limits under load. With Supabase as the layer, your app's reads and writes hit Postgres, which has no HubSpot rate limit, and the sync consolidates changes into batched, retried HubSpot calls that stay inside the limits. Read traffic in particular no longer touches HubSpot at all.
Is the Supabase copy of HubSpot data real-time or a nightly export?
Real-time. This pattern uses a live two-way sync driven by change data capture, not a nightly export or batch job. A change in HubSpot lands in Supabase within seconds, and a change in Supabase is pushed to HubSpot the same way. That is what lets you treat Supabase as the interface your app reads and writes, rather than a stale reporting copy.
Do I still need HubSpot if I query everything from Supabase?
Yes. HubSpot stays the CRM your go-to-market team works in, with its own UI, workflows, and reporting. The pattern does not replace HubSpot; it removes the HubSpot API from your application code. Your developers build against Supabase, and the sync keeps the two systems as one live dataset so both sides always agree.

About the author

Ruben Burdin
Founder & CEO

Ruben Burdin is the Founder and CEO of Stacksync, the first real-time and two-way sync for enterprise data at scale. Ruben is a Y Combinator alumni with a strong background in software engineering and business.

All posts by Ruben Burdin

About Stacksync

Stacksync powers real-time, two-way sync between CRMs, ERPs, and databases. Engineers sync data at scale and automate workflows, not dirty API plumbing.

Coworkers laughing in front of a laptop in a casual office setting

Your last integration took months.
Your next one takes a prompt.