Blog

Call the HubSpot API From Make With a Code Step

Updated November 2026

When Make's HubSpot CRM app has no module for the call you need, run the request yourself: add the CustomJS Execute Inline JavaScript module, map your private app token and filter values into its Input field, and call https://api.hubapi.com with fetch or the preinstalled @hubspot/api-client package. The module outputs whatever your code returns, so a HubSpot search response comes out as a flat array that the next module maps directly.

The gaps are concrete. We checked Make's HubSpot CRM module list at apps.make.com/hubspotcrm in October 2026: no batch create, update or upsert module, no search module for custom object records, and associations one pair per operation. Make's generic Make an API Call module reuses the connection's auth, but it returns raw JSON you still have to flatten and cannot loop over pages.

TL;DR

  • Make's HubSpot CRM app (checked October 2026): no batch modules, no custom object search, associations one pair per operation.
  • A code step posts to /crm/v3/objects/contacts/search with filter groups and returns a flat array for 1 Make credit.
  • Map the private app token into the Input field from a Make custom variable or data store record. Never paste it into the code.
  • HubSpot search limits: 5 filter groups, 18 filters, 200 per page, 10,000 per query, 5 requests per second.

Which HubSpot calls does Make's HubSpot CRM app not cover?

Three gaps, verified against the module list in October 2026:

  • Batch endpoints. /batch/create, /batch/update and /batch/upsert have no module. Native Create and Update handle one record per operation; one batch call from code sends up to 100 records for 1 operation.
  • Custom object search. The app has Create, Get, Update and Delete a Custom Object Record and a generic Search for CRM Objects module whose operators Make's docs do not list. For AND/OR groups across several properties, build the body yourself.
  • Associations in bulk. Create, List and Delete an Association work one pair at a time. Linking one deal to 40 contacts is 40 operations, or one call to the v4 batch endpoint.

How do I search HubSpot contacts with a filter group from a Make code step?

In HubSpot, create a private app (Settings, Integrations, Private Apps) with the crm.objects.contacts.read scope and copy the token. In Make, add the Execute Inline JavaScript module and put this JSON in its Input field, with the token and filter values mapped from earlier modules:

{
  "token": "{{ mapped from a Make custom variable or data store }}",
  "lifecycleStage": "lead",
  "createdAfter": "2026-10-01T00:00:00Z",
  "limit": 50
}

The code converts the ISO date to the millisecond timestamp HubSpot expects, runs the search, and flattens the response. Set Return Type to Array:

const data = typeof input === "string" ? JSON.parse(input) : input;

const body = {
  filterGroups: [{
    filters: [
      { propertyName: "lifecyclestage", operator: "EQ", value: data.lifecycleStage },
      { propertyName: "createdate", operator: "GTE",
        value: String(new Date(data.createdAfter).getTime()) }
    ]
  }],
  properties: ["email", "firstname", "lastname", "company", "createdate"],
  sorts: [{ propertyName: "createdate", direction: "DESCENDING" }],
  limit: data.limit || 100
};
const res = await fetch("https://api.hubapi.com/crm/v3/objects/contacts/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${data.token}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(body)
});
if (!res.ok) throw new Error(`HubSpot ${res.status}: ${await res.text()}`);
const json = await res.json();
return json.results.map(c => ({
  id: c.id,
  email: c.properties.email,
  name: [c.properties.firstname, c.properties.lastname].filter(Boolean).join(" "),
  company: c.properties.company,
  createdAt: c.properties.createdate
}));

Output, as the next module sees it (an Iterator turns it into one bundle per contact):

[
  {
    "id": "151801",
    "email": "[email protected]",
    "name": "Maria Schulz",
    "company": "Nordwind GmbH",
    "createdAt": "2026-10-06T08:41:12.339Z"
  },
  {
    "id": "151742",
    "email": "[email protected]",
    "name": "Tunde Okafor",
    "company": "Brightline",
    "createdAt": "2026-10-03T15:02:48.110Z"
  }
]

The median inline script in our logs finishes in 121 ms; this one adds one round trip to api.hubapi.com, and the call is billed as 1 Make credit regardless. Endpoint and limits were checked against HubSpot's CRM search docs in October 2026: POST /crm/v3/objects/{object}/search, up to 5 filterGroups (OR between groups, AND inside), 18 filters total, operators including EQ, GTE, IN, CONTAINS_TOKEN and HAS_PROPERTY, 200 results per page, 10,000 per query, 5 requests per second per account. For more pages, loop on json.paging.next.after and send it as after, inside the 30 s (free) or 60 s (paid) timeout.

Prefer the official SDK? @hubspot/api-client is preinstalled on every CustomJS plan (npm package list). The same search:

const hubspot = require("@hubspot/api-client");
const client = new hubspot.Client({ accessToken: data.token });
const json = await client.crm.contacts.searchApi.doSearch(body);
return json.results;

HubSpot also publishes dated paths such as /crm/objects/2026-09/{object}/search. The v3 search page carried no deprecation notice in October 2026, and the SDK still targets v3.

Use our Make App to execute JavaScript directly in Make.

Where should the HubSpot private app token live?

Not in the JavaScript Code field: code travels in plain text with every blueprint export and clone. Put the token in a Make custom variable (organization or team level; Pro, Teams and Enterprise Make plans per Make's help center, October 2026) or, on any plan, in a Data store record read by Get a Record. Map it into Input and read it as input.token. Grant the private app only the scopes the call needs.

Native HubSpot module, HTTP module or code step: which one do I use?

OptionAuth handlingBatchCustom objectsUse when
Native HubSpot CRM moduleMake connection, OAuth, nothing to storeNo, one record per operationCreate, Get, Update, Delete, generic searchA module exists for the call
Make an API Call or HTTP moduleMake an API Call reuses the connection; HTTP needs the Bearer header each timeYes, raw request; response is raw JSONAny endpoint, raw responseOne call, no reshaping, no paging
CustomJS code stepToken mapped into InputYes, builds the payload and reads the response in 1 operationAny endpoint, response reshaped to flat fieldsRequest, paging and reshaping belong together

The general pattern is in custom API calls from Make. For a PDF from a HubSpot deal or quote, see the HubSpot PDF guide.

When Make's built-in is enough

  • Single-record work on contacts, companies, deals or tickets. Native modules exist, and the connection handles OAuth and token refresh.
  • Triggers. Watch Contacts, Watch Deals and the other Watch modules have no code-step equivalent.
  • One raw call with no reshaping. Make an API Call sends it with the connection's auth.
  • Low volume. 20 updates a day is 20 operations; batch calls pay off in the hundreds per run.
  • No private apps allowed. The native app signs in with OAuth and needs no token.

Paste the snippet into an Execute Inline JavaScript module, map the token and filters into Input, and run it. The free tier covers 600 requests per month, no credit card.

Get a free API key

Frequently Asked Questions

Related Articles

Continue reading on similar topics

npm Packages in Make: What You Can Use on Which Plan
·Guide

npm Packages in Make: What You Can Use on Which Plan

Make's Code app ships moment, moment-timezone and lodash below Enterprise. CustomJS adds more than 40 npm packages on every plan, including free. Plan-by-plan table and a working example for dates, data, HTML, PDF, tokens, HTTP and SDKs.

makemake-comnpm