Get your dream built 10x faster

Replit and HubSpot Integration: 2026 Guide

We build custom applications 5x faster and cheaper 🚀

Book a Free Consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.

Book a free consultation

How to Integrate Replit with HubSpot

Replit integrates with HubSpot the same way it would from any other runtime: using HubSpot’s public APIs (REST or GraphQL) over HTTPS, authenticated with either a Private App Access Token or an OAuth 2.0 flow. In a Repl, you store credentials in Replit Secrets, call HubSpot APIs through fetch or a server library (like Express + axios or node-fetch), and optionally handle inbound webhooks from HubSpot by exposing a public URL via Replit’s web server port. There’s no “Replit-specific” HubSpot integration — everything is explicit and uses HubSpot’s documented endpoints and authentication methods.

 

How Integration Works Conceptually

 

You’re basically building a small backend app inside Replit that talks to HubSpot via HTTPS. Replit runs your code (like a Node.js or Python app), you store tokens as environment variables, and your app uses them to call HubSpot API endpoints such as creating contacts, updating deals, or listening to CRM webhooks. Since Replit provides a public URL for running Repls, you can also receive callbacks or webhooks from HubSpot in real time.

  • HubSpot API: The interface that allows external services to read/write data inside your HubSpot account.
  • Replit Secrets: Secure way to store access tokens or client credentials so they aren’t visible in your code.
  • Replit Web Server: A process that responds to HTTP requests at a public URL, ideal for webhook integration.

 

Step-by-step Example (Node.js in Replit)

 

This example shows creating a contact in HubSpot CRM from a Node.js Replit app using a Private App Access Token.

 

// index.js

import express from "express"
import fetch from "node-fetch"

const app = express()
app.use(express.json())

// Replit Secret should store your HubSpot private app access token
const HUBSPOT_TOKEN = process.env.HUBSPOT_TOKEN

app.post("/create-contact", async (req, res) => {
  try {
    const response = await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${HUBSPOT_TOKEN}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        properties: {
          email: req.body.email,
          firstname: req.body.firstname,
          lastname: req.body.lastname
        }
      })
    })

    const data = await response.json()
    res.json(data)
  } catch (error) {
    console.error(error)
    res.status(500).json({ error: "Error creating contact" })
  }
})

// Replit server binds to 0.0.0.0 and exposes via its public URL
app.listen(3000, "0.0.0.0", () => {
  console.log("Server running on port 3000")
})

 

Configure Replit

 

  • Open your Repl → "Secrets" panel → Add key HUBSPOT\_TOKEN with your HubSpot Private App Access Token value.
  • Run the Repl — it will expose a public URL under something like https://your-repl-name.username.repl.co.
  • Send a POST request to /create-contact endpoint with a JSON body containing email, firstname, and lastname.

 

curl -X POST https://your-repl-name.username.repl.co/create-contact \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","firstname":"Jane","lastname":"Doe"}'

 

Webhook Handling (Optional)

 

If you want HubSpot to send you data automatically (like when contacts are updated), you create an endpoint in your Replit web server and register it in HubSpot under “Developer Account → Webhooks”. HubSpot will POST JSON payloads to your public Replit URL, which you verify using the provided signature headers.

 

app.post("/hubspot-webhook", (req, res) => {
  console.log("Webhook received from HubSpot:", req.body)
  res.sendStatus(200) // Always respond quickly to acknowledge
})

 

Production Considerations

 

  • Replit restarts inactive Repls — for long-running integrations, use Replit Deployments (Always On).
  • Keep tokens in Replit Secrets, never hardcode them.
  • For high-volume or stateful operations (like bulk syncs), offload heavy jobs to an external server or queue.
  • Use HTTPS endpoints only (Replit URLs are already HTTPS).

 

With this setup, you’ve built a real, functioning HubSpot integration running entirely in Replit’s environment — secure, simple, and based on the official APIs.

Use Cases for Integrating HubSpot and Replit

1

<h3>Sync HubSpot Contacts with a Replit App Database</h3>

Connect HubSpot’s Contact API to a Replit-hosted backend (for example, a Node.js app). This lets your Replit app automatically fetch and store HubSpot contact data in your own database or in-memory cache. It’s useful when your app needs HubSpot customer info to personalize a user dashboard or trigger actions based on CRM activity. Use Replit Secrets to store the HubSpot API key or OAuth token, and run your sync as a Replit Workflow so it executes periodically or on-demand. This integration follows explicit REST calls and uses environment variables for secure credentials handling.

  • Replit Secret: HUBSPOT_API_KEY=your_private_key
  • Bind Web Server: use server.listen(8080, "0.0.0.0") to expose your app.
  • Fetch Contacts: call HubSpot’s /crm/v3/objects/contacts endpoint via HTTPS.
import express from "express"
import fetch from "node-fetch"

const app = express()

app.get("/sync", async (req, res) => {
  const r = await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
    headers: { Authorization: `Bearer ${process.env.HUBSPOT_API_KEY}` }
  })
  const data = await r.json()
  res.json(data)
})

app.listen(8080, "0.0.0.0", () => console.log("Server running"))

2

<h3>Sync HubSpot Contacts with a Replit App Database</h3>

HubSpot can send real-time updates (webhooks) when contacts, deals, or tickets change. You can receive those webhook POST requests directly in a Replit-hosted Express app. This is reliable for integrating lead updates into other systems or triggering follow-up actions. Keep in mind that Replit restarts occasionally, so keep logic stateless or forward the data to an external store. Use Replit’s live view and console to debug webhook requests while HubSpot sends test events.

  • HubSpot Setup: Add your Repl’s public URL as a webhook subscription target.
  • Verification: HubSpot sends a verification request; your endpoint must respond with HTTP 200.
  • Data Handling: Process req.body and store or forward it.
import express from "express"
const app = express()
app.use(express.json())

app.post("/hubspot/webhook", (req, res) => {
  console.log("Received HubSpot event:", req.body)
  res.sendStatus(200)
})

app.listen(8080, "0.0.0.0", () => console.log("Listening for HubSpot webhooks"))

3

<h3>Automate Lead Follow-up Emails from Replit</h3>

Create a lightweight automation app that uses HubSpot’s Engagements or CRM APIs to detect new leads and sends follow-up emails or Slack notifications automatically. This app can run as a Replit Workflow triggered hourly or manually. It retrieves new leads via REST, checks certain conditions (for example new deal stage), then triggers HubSpot’s email API or integrates another outbound channel. Keeping it inside Replit lets you prototype business automation with real API events before moving to a production platform.

  • Workflow: In Replit, create a scheduled Workflow that runs node app.js.
  • API Calls: Use /crm/v3/objects/deals for deal info, and /marketing/v3/transactional-emails/single-send for outbound.
  • Secrets: Store tokens securely in Replit Secrets for HubSpot and Slack APIs.
import fetch from "node-fetch"

async function run() {
  const deals = await fetch("https://api.hubapi.com/crm/v3/objects/deals", {
    headers: { Authorization: `Bearer ${process.env.HUBSPOT_API_KEY}` }
  }).then(r => r.json())

  for (const d of deals.results) {
    if (d.properties.dealstage === "new") {
      await fetch("https://api.hubapi.com/marketing/v3/transactional-emails/single-send", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.HUBSPOT_API_KEY}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ emailId: "12345", message: { to: "[email protected]" } })
      })
    }
  }
}

run()

Book Your Free 30‑Minute Migration Call

Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.

Book a Free Consultation

Troubleshooting HubSpot and Replit Integration

1

Why is the HubSpot API key not being recognized in Replit Secrets?

The HubSpot API key isn’t being recognized in Replit Secrets because it’s either not properly set as an environment variable or the Repl environment hasn’t been restarted after adding it. Replit Secrets are injected into your runtime as environment variables, and your code must read them exactly by key name — case-sensitive — using process.env in Node.js.

 

Check and Fix Step-by-Step

 

  • Verify the secret name in the Replit sidebar under "Secrets" — it must match your code reference (for example HUBSPOT_API_KEY).
  • Never include quotes when setting the value — just paste the raw key.
  • Restart your Repl or Deployment after saving secrets, because Replit injects them only on startup.
  • Confirm runtime usage with a quick check inside the shell: echo $HUBSPOT_API_KEY
  • Use correct environment access inside code:

 

// Access HubSpot API key stored in Replit Secrets
const hubspotKey = process.env.HUBSPOT_API_KEY;

if (!hubspotKey) {
  console.error("HubSpot API key not found. Check Replit Secrets and restart your Repl.");
}

 

Once the key resolves correctly, HubSpot calls (e.g., via axios or official SDK) will authenticate normally. Misnaming the key or expecting automatic import breaks auth immediately.

2

How to fix CORS errors when sending requests from Replit to HubSpot API?

CORS errors happen because browsers block frontend JavaScript from calling external domains like HubSpot directly. To fix this in Replit, never call the HubSpot API from client-side code. Instead, build a small backend proxy in your Repl (Node.js or Python) that runs server-side and makes the HubSpot API request using your secret key or OAuth token. The browser talks only to your Replit server (same origin), eliminating the CORS issue.

 

How to Fix It Step-by-Step

 

  • Hide credentials in Replit Secrets — create environment variables like HUBSPOT\_TOKEN.
  • Create an Express server — the server receives frontend requests, then calls HubSpot via fetch or axios.
  • Expose via a mapped port — bind to 0.0.0.0 and open an HTTP route (e.g. /api/contacts).
  • From frontend — use fetch('/api/contacts') to communicate with your Repl backend.

 

// server.js
import express from "express"
import fetch from "node-fetch"

const app = express()
app.use(express.json())

app.get("/api/contacts", async (req, res) => {
  const response = await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
    headers: { Authorization: `Bearer ${process.env.HUBSPOT_TOKEN}` }
  })
  const data = await response.json()
  res.json(data)
})

app.listen(3000, "0.0.0.0", () => console.log("Server running"))

 

This proxy pattern works reliably in Replit Workflows or Deployments, avoids CORS entirely, and keeps tokens secret on the server.

3

Why does the Replit fetch request to HubSpot return a 401 unauthorized error?

A 401 error from HubSpot when using fetch inside a Replit Repl almost always means the authorization header (your HubSpot API key or access token) is missing, malformed, or expired. In Replit, this often happens if the secret isn’t read correctly from process.env, or if you’re trying to call the API directly from the browser instead of through the server side of your Repl, which exposes the token publicly and gets blocked.

 

How to fix and verify

 

Check that your token is saved in Replit Secrets (the lock icon on sidebar), then used server‑side only in your fetch call via process.env. HubSpot’s APIs require either a Private App token (“Bearer …”) or an OAuth access token. Always include the correct header and make sure the token has not expired.

  • Use only HTTPS endpoints like https://api.hubapi.com/crm/v3/objects/contacts
  • Never expose tokens in client code — route requests through your Express server in Replit.
  • If you recently rotated credentials in HubSpot, update the Replit secret too.

 

// Example of a valid server-side call in Replit
import fetch from "node-fetch"

const HUBSPOT_TOKEN = process.env.HUBSPOT_PRIVATE_APP_TOKEN

const res = await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
  headers: { 
    "Authorization": `Bearer ${HUBSPOT_TOKEN}`,
    "Content-Type": "application/json"
  }
})

const data = await res.json()
console.log(data)

 

Book a Free Consultation

Schedule a 30‑Minute No‑Code‑to‑Code Consultation

Grab a quick video call to discuss the fastest, most cost‑efficient path from no‑code to production‑ready code. Zero sales fluff—just practical advice tailored to your project.

Contact us

Common Integration Mistakes: Replit + HubSpot

Missing Public URL for HubSpot Webhooks

Developers often forget that Replit Repls run behind a dynamic preview URL that changes when restarted. HubSpot webhooks need a fixed, publicly reachable HTTPS endpoint to send events to. If you don’t use the correct exposed URL or deploy with an explicit mapped port, HubSpot can’t verify or reach your webhook.

  • Workaround: Always bind your Express server to 0.0.0.0 and use Replit’s assigned public URL or a Deployment for stable access.
import express from "express"
const app = express()
app.post("/webhook", (req, res) => { res.sendStatus(200) })
app.listen(3000, "0.0.0.0")  // Bind for Replit public access

Exposing Secrets Directly in Code

Copying your HubSpot Private App token directly into the source leads to leakage the moment someone forks or views the Repl. Replit offers Secrets for this reason — they store tokens as environment variables only available at runtime. Always read sensitive values with process.env instead of hardcoding.

  • Risk: Anyone who sees your code can steal your HubSpot credentials.
  • Fix: Add tokens in Replit → Tools → Secrets, then reference them in code.
const HUBSPOT_TOKEN = process.env.HUBSPOT_TOKEN
const headers = { Authorization: `Bearer ${HUBSPOT_TOKEN}` }

Using OAuth Redirects Without Persistent URL

HubSpot OAuth apps require a fixed redirect URI. Replit’s running Repls generate a new URL each session, breaking OAuth callbacks. HubSpot will reject authorization if the redirect URL doesn’t match exactly. To integrate properly, deploy your Repl or use a Replit Deployment URL which stays stable.

  • Tip: In HubSpot’s app settings, set the redirect URL to your deployment domain.
// Redirect URL must match exactly what you registered in HubSpot
const REDIRECT_URI = process.env.REDIRECT_URI
app.get("/auth/hubspot/callback", async (req, res) => { /* handle tokens */ })

Ignoring Rate Limits and Process Restarts

Replit processes can restart anytime, and HubSpot applies API rate limits. Without caching or persistence outside Replit, integrations can lose sync state or repeatedly fail. If you rely only on in-memory variables, they reset when the Repl sleeps or rebuilds. Always plan for idempotent requests and store data in HubSpot or an external database.

  • Solution: Queue or log updates externally, respect HTTP 429 retry headers, and never assume local memory persists.
if (response.status === 429) {
  const retryAfter = response.headers["retry-after"]
  await new Promise(r => setTimeout(r, retryAfter * 1000))
}

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

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.Â