Skip to main content

HubSpot Setup

Configuring a custom HubSpot public app for use with Caddi

Caddi connects to HubSpot through a custom public app in a HubSpot developer account. HubSpot changed how these are created in mid-2026 — the app is now defined in code and uploaded with the HubSpot CLI rather than created through a form.

HubSpot disabled the old UI-based public app creation flow in June 2026. There is no longer a "Create app" button for new public apps. Apps are now created on the Projects-based developer platform using the HubSpot CLI, which means this setup needs someone comfortable with Node and a terminal.

Existing legacy public apps keep working. If you find instructions describing a point-and-click creation flow, they predate the change.

Get the required scope set right the first time. Changing requiredScopes after customers have installed the app forces every one of them to re-authorize. Tier-dependent scopes belong in optionalScopes instead.

Before you start

You'll need:

  • A free HubSpot developer account at developers.hubspot.com — separate from your normal HubSpot portal

  • HubSpot CLI v7.6.0 or later, with Node installed

  • Owner or Admin access to your Caddi organization

  • A HubSpot Super Admin (or a user with integration-install permission) to authorize the connection

A HubSpot developer test account is worth creating for isolated testing before you point the app at a live portal.

Step 1: Set up the CLI and create the project

  1. Create or sign in to a developer account at developers.hubspot.com.

  2. Install the CLI: npm i -g @hubspot/cli

  3. Authenticate: hs account auth

  4. Run hs project create, choose the App template, select Marketplace distribution, and choose OAuth authentication.

Step 2: Configure the app and upload it

The app's redirect URL and scopes live in src/app/app-hsmeta.json.

Scopes map to HubSpot Hub tiers. If a requiredScopes entry names a scope the installing portal's tier doesn't have, the install fails outright with no partial success. Put anything tier-dependent — custom objects need Enterprise, for example — in optionalScopes.

  1. Open src/app/app-hsmeta.json in the generated project.

  2. Set config.auth.redirectUrls to include https://app.trycaddi.com/oauth-callback. It's an array, so multiple URLs are allowed, and localhost is permitted for development.

  3. Set the scope arrays:

    • requiredScopes — core CRM read and write, for example crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.companies.read, crm.objects.companies.write, crm.objects.deals.read, crm.objects.deals.write, crm.objects.owners.read, and the matching crm.schemas.*.read scopes

    • optionalScopes — anything tier-gated or non-essential, such as tickets, crm.objects.custom.read, crm.objects.custom.write, crm.lists.read, crm.lists.write, files

  4. Leave the uid value alone once you've uploaded — changing it makes HubSpot treat the app as brand new.

  5. Run hs project upload.

Note that the ticket scope is the legacy string tickets, not crm.objects.tickets.read. Leave settings.users.* and crm.objects.users.* off — those are user management.

Step 3: Copy the credentials

  1. In your developer account, go to Development → Projects, open your project, and click your app's name under Project Components.

  2. Open the Auth tab.

  3. Copy the Client ID and Client Secret from Client credentials.

  4. Confirm the Redirect URLs listed at the bottom of the page match what you uploaded.

Step 4: Configure HubSpot in Caddi

This step must be completed by a Caddi organization owner or admin.

  1. In Caddi, open Integrations in the left sidebar, then click the Integration Setup tab at the top of the page. This tab is only visible to organization owners and admins.

  2. Find HubSpot in the list and click Configure.

Enter the following values:

  • Client ID — from the app's Auth tab

  • Client Secret — from the same tab. This can be rotated there if needed.

  • OAuth Scopes — space-separated list matching your requiredScopes. Leave blank to use Caddi's defaults.

  • Optional OAuth Scopes — space-separated list matching your optionalScopes. Users can decline these without the install failing.

Click Save Configuration. Caddi validates the credentials immediately — if something is wrong you'll see an error right away, and nothing is stored until validation passes.

Step 5: Connect your account

  1. Go back to the My Connections tab and find HubSpot.

  2. Click Connect + and sign in to HubSpot.

  3. Select the HubSpot account to connect and approve the request.

  4. You'll be returned to Caddi with the connection active.

How the connection behaves

  • Access tokens last 30 minutes and refresh automatically.

  • Refresh tokens are long-lived but are invalidated by three things: uninstalling the app, rotating the client secret, and changing the app's required scopes. Any of those means users reconnect.

  • Rotating the client secret invalidates existing tokens. Schedule it rather than doing it mid-day.

  • A custom connection replaces the standard one. Members of your organization will only see the option to connect through your app.

  • Rate limits are per-portal and depend on your HubSpot tier.

  • Revoking access. Uninstall the app from the HubSpot portal, or delete it from the developer account.

Troubleshooting

There's no button to create a public app

Expected as of June 2026. Public apps are created with the HubSpot CLI on the Projects platform — see Step 1.

Installation fails immediately for a customer portal

A requiredScopes entry names a scope that portal's HubSpot tier doesn't include. Move the tier-dependent scopes to optionalScopes and re-upload.

A user sees a "Request for Integration Permissions" error

That HubSpot user lacks permission to install integrations. A Super Admin needs to install it, or grant them the permission.

Everyone was disconnected after a config change

Changing requiredScopes or rotating the client secret invalidates existing refresh tokens. Users need to reconnect once.

Loops can't reach custom objects

Custom object scopes require HubSpot Enterprise. Check the portal's tier, and make sure those scopes are in optionalScopes so other portals still install.

Still stuck? Contact Caddi support with the exact error message you're seeing and the time it occurred.

Automation ideas

Law Firms

Inbound enquiry → qualified contact and task

Caddi reads an enquiry, creates or updates the HubSpot contact with the enquiry detail, and creates the follow-up task for the right attorney.

Engagement signed → deal closed and matter opened

When an engagement letter completes, Caddi closes the HubSpot deal and opens the matter in your practice management system.

RIAs

Prospect meeting → CRM update

Caddi pulls the meeting summary and updates the HubSpot contact with topics discussed, next steps, and the follow-up date.

Pipeline stage change → onboarding kickoff

When a deal reaches the closed-won stage, Caddi starts the onboarding sequence and creates the account records downstream.

Client review cycle → outreach sequence

Caddi identifies clients due for review from HubSpot data and drafts the outreach, with the advisor approving before anything sends.

Did this answer your question?