Guides / n8n × HubSpot / Migration

Fix HubSpot deprecated API endpoints: migrate legacy v1 and v2 calls to v3

Plan a safe HubSpot API migration from deprecated v1 or v2 endpoints to supported v3 resources with mapping, pagination, authentication, and QA.

Advertisement
Illustrated troubleshooting diagram for Fix HubSpot deprecated API endpoints: migrate legacy v1 and v2 calls to v3.
Short answer: Inventory every legacy URL, find the current supported replacement in HubSpot’s API reference and changelog, map request and response fields, replace authentication only as needed, and test pagination and associations. Run old and new reads side by side before disabling the legacy route. Do not assume a v3 endpoint returns the same records or defaults. Legacy-style pattern: Current CRM object pattern: The path, pagination cursor, property selection, and response fields all need review.

Build the endpoint inventory

Search application code, workflow exports, serverless functions, cron scripts, documentation, and monitoring rules for `/v1/`, `/v2/`, old SDK method names, and legacy query parameters. Record HTTP method, URL, caller, portal, object, frequency, read/write behavior, pagination method, and business owner.

Separate routes that only read from routes that mutate data. A read migration can run in shadow mode; a write migration needs idempotency and rollback. Mark unknown routes as production risk until a real request trace identifies them.

Find the supported replacement

Use HubSpot’s current API reference for the resource and the developer changelog for sunset notices and dates. A route may have moved into CRM objects, search, associations, imports, files, or a dedicated settings API. The replacement may require a different scope and may not expose every legacy field.

Record the replacement URL, required scopes, supported filters, page size, cursor rules, archive behavior, and rate-limit notes. Treat the changelog as time-sensitive. Recheck before launch because an API page can change after the first design review.

Advertisement

Map the data contract

Create a table for every field: legacy name, v3 name, type, source of truth, transformation, nullable behavior, and verification query. Include object ID, created and updated timestamps, archived state, owner, pipeline, stage, custom properties, and associations.

Do not map UI labels to API keys. Fetch property definitions from the target portal and use internal names. For enum values, map the internal option value. For dates, convert to the documented representation. For amounts, use a numeric representation accepted by the target property.

Rewrite pagination deliberately

Older APIs may use offset, `hasMore`, or a different page token. Current collection APIs commonly return `results` and a `paging.next.after` cursor. The client must stop when the cursor is absent and must not request the same cursor forever.

Example cursor loop:

Store a checkpoint for long exports. Test an empty page, one page, multiple pages, a deleted record, and a token or network failure between pages.

let after;
do {
  const url = new URL("https://api.hubapi.com/crm/v3/objects/contacts");
  url.searchParams.set("limit", "100");
  if (after) url.searchParams.set("after", after);
  const page = await get(url, token);
  for (const record of page.results ?? []) await consume(record);
  after = page.paging?.next?.after;
} while (after);

Plan writes and associations

For creates, choose an idempotency key in your system and search by a stable business key before creating. For updates, use the HubSpot record ID. For associations, check the current association API and type ID; a legacy relationship field may not translate directly.

Use a dry-run mapper that reports missing properties and unsupported fields. Write to a staging portal or a small allowlist first. Capture before and after values. If the new API returns a different error category, classify it instead of retrying every 4xx.

Authentication and scopes

Legacy examples often use API keys or older SDK authentication. Current integrations should use a private-app token for a single controlled portal or OAuth for a multi-tenant product. The new route may require scopes that the old route did not expose. A 401 is credential state; a 403 is usually scope or account access; a 404 can mean a bad route or ID.

Rotate credentials independently from the endpoint migration so one failure does not obscure the other. Keep the old and new clients behind separate configuration flags and log a credential alias, never the token.

Warning: do not leave a fallback that silently retries a sunset endpoint forever. It can consume quota and hide that production still depends on unsupported behavior.

Shadow-read and cutover plan

For reads, call both clients for a sampled set, normalize records, and compare IDs, property values, counts, and timestamps. Explain intentional differences such as archived records, omitted properties, or association pagination. Alert on unexplained differences.

For writes, send the v3 request only to a test scope first. Verify the record with a fresh read. Then enable a small production cohort, monitor 4xx, 5xx, latency, rate-limit headers, duplicate creates, and reconciliation differences. Expand only when the cohort is stable.

Manual QA checklist

Test every inventoried route, authentication model, object type, custom property, enum, date, association, page boundary, empty result, archived record, duplicate request, timeout, 401, 403, 404, and 429. Confirm retry policy distinguishes transient errors from invalid requests.

Run a count reconciliation and a sample-by-ID comparison. Verify scheduled exports and rarely used admin scripts. Search the built artifact and deployment configuration for `/v1/`, `/v2/`, `hapikey`, and deprecated SDK calls after the cutover. Keep a rollback switch, but make it point to a supported path whenever possible.

What a complete migration record contains

Keep the inventory, replacement decision, field map, required scopes, sample requests, comparison results, launch owner, and retirement date in one change record. For every intentionally unsupported legacy field, record the business decision and replacement behavior. “Not returned by v3” is not a mapping; it is an open question until someone decides whether to omit, derive, or source the value elsewhere.

Repeat the inventory after deployment from compiled artifacts and runtime traces. Old routes often survive in a low-frequency billing export, a support script, or a disabled-looking workflow that is enabled by a schedule. Set an alert for any legacy URL observed after the retirement date. Review the alert weekly until the old path is removed from the network policy.

If HubSpot publishes a new sunset notice, compare its effective date with your release calendar and customer contracts. Create a feature flag that can stop writes without deleting checkpoints. This gives support a controlled response if a replacement behaves differently in a particular portal.

Add a migration acceptance record

For every retired route, store the old URL, replacement URL, method, scopes, pagination model, fields intentionally omitted, sample count comparison, owner, and retirement date. A route is not migrated merely because the new request returns 200. The acceptance record should show that the downstream consumer receives the same business meaning or document the approved difference.

Where these facts come from

Advertisement
Advertisement