Guides / n8n × HubSpot / Authentication

HubSpot API key removed: how to migrate a hapikey integration to a private app token

Replace legacy HubSpot hapikey authentication with a private app token and verify scopes, headers, errors, and rollout safety.

Advertisement
Illustrated troubleshooting diagram for HubSpot API key removed: how to migrate a hapikey integration to a private app token.
Short answer: Create or use a HubSpot private app, grant only the scopes the integration needs, copy its access token into a server-side secret store, and replace the query parameter with an Authorization Bearer header. Test every endpoint and tenant before removing the legacy path. Do not put the token in browser code or URLs. Old request: New pattern: The endpoint may also need migration separately; authentication and API-version migration are related but distinct tasks.

Private app or OAuth?

Use a private app for a controlled integration inside one HubSpot account. It is quick to configure and gives the administrator a clear scope list. Use OAuth when your software is installed by multiple HubSpot customers or must request consent per account. Do not distribute one private-app token to all customers.

Create the replacement safely

In HubSpot, open the developer or integration settings used by your account, create or select a private app, describe its purpose, and grant the minimum scopes. Start with read access for a reporting test. Add write scopes only after the read path works. Save the token once in a secret manager; do not commit it to a workflow export.

Record the app name, account, scopes, owner, created date, rotation date, and systems that use it. This turns an emergency token rotation into a documented operation.

Advertisement

Change the HTTP client

Put authentication in one client wrapper:

Remove hapikey from query construction. URLs are commonly stored in proxies, analytics, browser history, and error logs. A header is not a substitute for secret management, but it reduces accidental disclosure.

const response = await fetch(url, {
  headers: {
    Authorization: "Bearer " + token,
    "Content-Type": "application/json"
  }
});

Test scopes and endpoint versions

A valid token can still receive 403 when its private app lacks a required scope. Test reads, creates, updates, and associations separately. If the endpoint is a legacy v1 or v2 route, check HubSpot’s current sunset and migration documentation rather than assuming a new token will revive it.

Use a test contact and a harmless property. Verify the response, then fetch the record again. A 200 response from a list endpoint does not prove that a write or association succeeded.

Rotate without downtime

Create the new private app token, deploy it through configuration, test one worker, then roll it to the rest. Keep the old secret only for the defined overlap window and revoke it afterward. If you cannot overlap, schedule the switch and monitor failures closely.

Do not print both tokens when debugging. Log a credential alias such as hubspot-prod-2026-09 and the last four characters only if necessary.

Common migration failures

A 401 usually means the token is missing, malformed, expired, or revoked. A 403 usually points to scope or account access. A 404 can indicate a retired endpoint, wrong object path, or incorrect ID. A 429 is rate limiting, not an authentication failure. Classify the response before changing credentials.

If the request works in curl but fails in n8n, Zapier, or Make, inspect whether the connector still appends hapikey, overwrites Authorization, or sends a second request with the old credential.

Audit after migration

Search repositories, workflow JSON, environment names, documentation, and logs for hapikey and old key fragments. Remove obsolete secrets from active systems. Check scheduled jobs and rarely used admin scripts. A migration is incomplete when the main API client is updated but an old weekly export still uses the retired key.

The trap: replacing hapikey with Bearer but keeping an obsolete endpoint. Authentication can be fixed while the route still requires a separate v3 migration.

A migration runbook

Begin with an inventory of every place the legacy key can hide: application code, environment variables, workflow exports, cron scripts, serverless settings, documentation, test fixtures, and observability tools. Search for hapikey and api_key without printing the secret in command output. Mark each consumer as production, staging, development, or unknown.

Create the private app with a named owner and a written purpose. Compare its scopes with the old integration’s actual calls. Run a read-only smoke test first, then test one controlled write and one association if the workflow needs them.

Deploy the new credential through the same secret path used by the application. Restart workers that cache environment variables. After cutover, revoke the old credential and inspect logs for attempts using the old path. Record the account, app, scopes, owner, and rotation date.

Security review

Bearer tokens grant access to the account available to the app. Keep them server-side, encrypt them at rest, redact them from errors, and limit who can rotate them. If a token appears in a public issue or browser bundle, treat it as compromised and revoke it immediately.

Verify the full migration

Test the replacement in a copy of the real workflow. Check a list request, one read by ID, one create or update, and one association if those operations are used. Compare the final record with the source, including custom properties and relationship IDs. A successful authentication request is only the first checkpoint.

Restart long-lived workers after changing the secret. Confirm that background jobs, webhooks, admin scripts, and scheduled exports all read the new credential alias. Search deployment configuration for the legacy query parameter and remove it only after the new path is confirmed. Keep a short overlap window if the old credential can be revoked safely, then revoke it and document the result.

If the token fails, classify the response before changing it: 401 for credential state, 403 for scopes or account access, 404 for route or record, and 429 for usage limits. Put failed writes in a review queue rather than replaying them blindly. This makes a security migration recoverable without creating duplicate CRM records.

Keep the private-app owner, account, scopes, and rotation date in the service inventory.

Include scheduled jobs and rarely used administrative scripts in the inventory; they are often the last consumers of the retired query parameter.

Verify that no legacy consumer remains

Make the migration complete only after searching code, workflow exports, cron definitions, serverless settings, observability queries, and documentation for `hapikey`, `api_key`, and the old endpoint family. A useful release check is to reject any outbound request whose URL contains the retired query parameter. Keep the rejection visible in logs without printing the key value, so a forgotten weekly job cannot quietly continue using the old path.

Where these facts come from

Advertisement
Advertisement