Skip to content

HubSpot - Search Objects

↩ Part of the HubSpot integration.

Searches records of one object type with HubSpot’s search endpoint (POST /crm/v3/objects/{object_type}/search) and returns the results array.

This is the node you use to answer “does this contact already exist?” before creating a duplicate, or to pull “every deal closing this month”. You write the search body as JSON, exactly as HubSpot documents it.

FieldTypeRequiredDescription
credentials_idcredentialsYesHubSpot credential
object_typetextYesObject type: contacts, companies, deals, tickets. Defaults to contacts if left empty
searchjsonYesSearch body: filterGroups, query, sorts, properties, limit

Both parameters accept dynamic variables; the search string is resolved as text before being parsed as JSON, so you can inject {{data.email}} into a filter value.

KeyWhat it does
filterGroupsArray of groups. Filters inside a group are combined with AND, groups with each other with OR. Each filter is { propertyName, operator, value }
queryFree-text search across the object’s searchable properties
sortsArray such as [{"propertyName":"createdate","direction":"DESCENDING"}]
propertiesArray of property names to return
limitResults per page (max 100)

Frequent operators: EQ, NEQ, LT, LTE, GT, GTE, BETWEEN, IN, NOT_IN, HAS_PROPERTY, NOT_HAS_PROPERTY, CONTAINS_TOKEN.

This module requires a HubSpot credential:

FieldDescription
tokenPrivate App token (starts with pat-), from HubSpot → Settings → Integrations → Private Apps

data is the array of matching records:

[
{
"id": "701",
"properties": {
"email": "ana@acme.com",
"firstname": "Ana",
"createdate": "2026-08-05T10:00:00.000Z",
"hs_object_id": "701"
},
"createdAt": "2026-08-05T10:00:00.000Z",
"updatedAt": "2026-08-05T11:22:00.000Z",
"archived": false
}
]

The total number of matches (not just the page) travels in _meta:

{ "moduleVersion": "1.0.0", "success": true, "count": 1, "total": 1, "objectType": "contacts", "totalMs": 320 }

An empty search returns [] and count: 0 — not an error. Branch on _meta.count (or on the array length) to decide between creating and updating.

{
"credentials_id": "hubspot_marketing",
"object_type": "contacts",
"search": {
"filterGroups": [
{ "filters": [{ "propertyName": "email", "operator": "EQ", "value": "{{data.email}}" }] }
],
"properties": ["email", "firstname", "lastname", "lifecyclestage"],
"limit": 1
}
}
{
"credentials_id": "hubspot_sales",
"object_type": "deals",
"search": {
"filterGroups": [
{
"filters": [
{ "propertyName": "amount", "operator": "GT", "value": "10000" },
{ "propertyName": "dealstage", "operator": "NEQ", "value": "closedlost" }
]
}
],
"sorts": [{ "propertyName": "amount", "direction": "DESCENDING" }],
"properties": ["dealname", "amount", "dealstage", "closedate"],
"limit": 50
}
}
{
"credentials_id": "hubspot_marketing",
"object_type": "companies",
"search": {
"query": "{{data.term}}",
"properties": ["name", "domain", "city"],
"limit": 20
}
}
  • Filters inside one group are AND; separate groups are OR. A single group with two filters means “both conditions”.
  • Values are always sent as strings, including numbers and dates — "10000", not 10000. Dates use ISO 8601 or a millisecond timestamp.
  • The maximum limit is 100, and HubSpot caps the total number of paged results per search; narrow the filters instead of paging forever.
  • HubSpot’s search index is eventually consistent: a record created seconds earlier may not appear yet. When you have just created it, read it with Get object by id.
  • If search is empty or does not parse as JSON, the node stops with a validation error before calling HubSpot.