Skip to content

When to Use CRM Search API vs. Object-Specific APIs


Navigating through HubSpot's APIs can be a bit like choosing the right tool for a job. Sometimes, you need the precision of a scalpel, and other times, you need the broad reach of a net. In the world of HubSpot, this translates to knowing when to use the CRM Search API and when to opt for an object-specific API. Let's dive in and demystify when to use each!

The CRM Search API: Casting a Wide Net

The CRM Search API is a powerful tool for searching within individual object types in your CRM. Still, it requires separate queries for each object type when dealing with multi-object searches across your CRM datasets. The CRM Search API is engineered to perform CRM searches, leveraging multiple queries that support complex search conditions and full-text search capabilities. For instance, when querying across multiple object types (e.g., contacts, companies, deals, or custom objects), you can execute a function that spans these diverse datasets, returning aggregated results. This is particularly advantageous when the target data may reside in various object types.

Below are some scenarios where the CRM Search API shines – let’s go!

Complex Queries Across Multiple Object Types

If you're working with HubSpot's CRM, you might encounter situations where you need to perform complex searches involving multiple object types like contacts, companies, and deals. However, the CRM Search API is designed to handle search queries on a per-object basis, so you cannot execute a single query that covers multiple object types simultaneously. But don't worry, there's a workaround to this limitation!

To start with, you need to know that the CRM Search API has separate endpoints for each object type. This means you'll have to send individual search requests for contacts, companies, deals, etc. Each request will return results specific to that object type.

Although HubSpot's CRM Search API doesn't support multi-object type queries by default, you can still perform complex searches across different object types with a bit of extra work. This can be done by making separate API requests and aggregating the results. Below is a conceptual example of how you might perform this in code.

First, ensure you have the requests library installed:

pip install requests

Here's the Python code example:

import requests # Define your search criteria for each object type contact_search_criteria = { "filterGroups": [ # ... your filters for contacts ], "sorts": [ # ... your sorting for contacts ], "properties": [ # ... properties you want to retrieve for contacts ], "limit": 10 # Adjust the limit as needed } company_search_criteria = { "filterGroups": [ # ... your filters for companies ], # ... other criteria } # ... repeat for other object types # Function to perform a search on a specific object type def search_hubspot_object(object_type, search_criteria): endpoint = f'{object_type}/search' headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {YOUR_HUBSPOT_ACCESS_TOKEN}' } response =, headers=headers, json=search_criteria) response.raise_for_status() # This will raise an exception for HTTP error responses return response.json()['results'] # Assuming 'results' contains the search results # Function to aggregate results from multiple searches def perform_complex_search(): try: contacts = search_hubspot_object('contacts', contact_search_criteria) companies = search_hubspot_object('companies', company_search_criteria) # ... repeat for other object types # Combine the results from different searches as needed combined_results = { 'contacts': contacts, 'companies': companies, # ... other object results } return combined_results except requests.HTTPError as http_err: print(f'HTTP error occurred: {http_err}') except Exception as err: print(f'An error occurred: {err}') # Execute the complex search if __name__ == '__main__': combined_results = perform_complex_search() print('Combined Search Results:', combined_results)

Remember to replace YOUR_HUBSPOT_ACCESS_TOKEN with your actual HubSpot access token in this example. Below, we’ll walk you through the code above on executing separate searches for multiple object types and aggregating the data. 

  • First, fill in the contact_search_criteria and company_search_criteria with the appropriate filters, sorts, and properties for your search.
  • Then, the search_hubspot_object function performs a POST request to the search endpoint for a given object type.
  • The perform_complex_search function calls search_hubspot_object for each object type and aggregates the results.
  • Error handling is done using requests.HTTPError to catch any HTTP-related errors and a general Exception to catch others.
  • Lastly, the script is set to run the perform_complex_search function if it's the main module being executed.

Remember to handle pagination if your search results exceed the page size limit, and adjust the error handling as needed for your specific use case.

Here's a helpful tip: the /search API endpoint is available in our CRM object APIs in Postman. You can reference and test it easily. To access the endpoint, navigate to the CRM object API, fork it, and then you can access the Postman collection that includes a Search folder for you to access the search endpoint for the desired object type.

Full-Text Search

If you want to perform a full-text search that scans through various text fields of your CRM records, the CRM Search API is your best bet. It's designed to handle these types of searches efficiently, helping you find records based on text content.

Here's an example of how you might set up a full-text search query in Python using the requests library again. This example will search across text fields for contacts, but you can adjust the object type and properties as needed for your use case.

import requests # Your HubSpot API Key api_key = 'your_api_key' # Endpoint for the CRM Search API url = f'{api_key}' # Headers for the request headers = { 'Content-Type': 'application/json' } # The search query payload for a full-text search payload = { "query": "Example Search Term", "limit": 10, "properties": ["email", "firstname", "lastname", "phone", "notes"], "filterGroups":[], "sorts": [] } # Make the POST request to the CRM Search API response =, headers=headers, json=payload) # Check for successful request and print results if response.ok: print(response.json()) else: print(f"Error: {response.status_code}") print(response.text)

In this example:

  • "query": "Example Search Term" is where you put the term you want to search for. The API will return records where this term appears in any of the specified properties.
  • "properties": ["email", "firstname", "lastname", "phone", "notes"] lists the properties you want to be returned for the object. The API will not limit its search to these fields; it searches across all default searchable properties defined for the object type in HubSpot's property settings.
    The default searchable properties for each object type are predetermined by HubSpot. For instance, when searching contacts, HubSpot may search through fields like firstname, lastname, and email by default, even if they are not listed in the properties parameter of your search query.

Here's a helpful tip: You can also search through associations using a special pseudo-property in your search query. This pseudo-property is formatted as associations.{objectType}, where {objectType} is the type of the associated object you're interested in (e.g., contact, company, deal, etc.). For more detailed information on how to use associations in your search queries, you can refer to the HubSpot documentation on searching through associations.

  • "filterGroups":[] and "sorts": [] are left empty, meaning no additional filters or sorting are applied to the search results.

Make sure to replace your_api_key with your actual HubSpot API key or access token and the "Example Search Term" with the term you're searching for. If you want to search across different object types (like companies or deals), you should adjust the URL and properties accordingly.

Dynamic Search Requirements

When your search needs are dynamic and require different filters and query structures on the fly, the CRM Search API provides the flexibility you need. It can handle various search configurations, making it ideal for building dynamic search-driven applications or dashboards.

Here's an example scenario where dynamic search requirements might be used:

Imagine you have a web application where sales representatives can search for contacts based on various criteria selected by the user, such as:

  • Contact creation date range
  • Email domain
  • Engagement score (a custom property)
  • Recent activity date

The sales representative can specify any combination of these criteria to refine their search. Here's how you might construct a dynamic search query for this scenario using HubSpot's CRM Search API:

import requests # Function to build a dynamic search payload based on user input def build_search_payload(date_range=None, email_domain=None, engagement_score=None, recent_activity=None): filter_groups = [] if date_range: filter_groups.append({ "filters": [ { "propertyName": "createdate", "operator": "GTE", "value": date_range['start'] }, { "propertyName": "createdate", "operator": "LTE", "value": date_range['end'] } ] }) if email_domain: filter_groups.append({ "filters": [ { "propertyName": "email", "operator": "CONTAINS_TOKEN", "value": email_domain } ] }) if engagement_score: filter_groups.append({ "filters": [ { "propertyName": "engagement_score", "operator": "GTE", "value": engagement_score } ] }) if recent_activity: filter_groups.append({ "filters": [ { "propertyName": "last_activity_date", "operator": "GTE", "value": recent_activity } ] }) return { "filterGroups": filter_groups, "limit": 10, "sorts": [ { "propertyName": "createdate", "direction": "DESCENDING" } ] } # Your HubSpot API Key api_key = 'your_api_key' # Endpoint for the CRM Search API url = f'{api_key}' # Headers for the request headers = { 'Content-Type': 'application/json' } # Example user input user_input = { "date_range": {"start": "2023-01-01", "end": "2023-12-31"}, "email_domain": "", "engagement_score": 50, "recent_activity": "2023-12-01" } # Build the dynamic search payload payload = build_search_payload( date_range=user_input.get("date_range"), email_domain=user_input.get("email_domain"), engagement_score=user_input.get("engagement_score"), recent_activity=user_input.get("recent_activity") ) # Make the POST request to the CRM Search API response =, headers=headers, json=payload) # Check for successful request and print results if response.ok: results = response.json() for contact in results.get('results', []): print(contact) else: print(f"Error: {response.status_code}") print(response.text)

In this code:

  • The build_search_payload function dynamically constructs the search payload based on the provided criteria.
  • The user_input dictionary simulates input from a user interface.
  • The search payload is built by calling build_search_payload with the user's criteria.
  • The API request is made with the dynamically constructed payload.

This approach allows the search functionality to be flexible and adapt to various user-defined search criteria without hardcoding the search parameters.

Object-Specific APIs: The Precision Tools

On the other side of the spectrum, we have object-specific APIs. These are your precision tools, designed to work with specific CRM objects like contacts, companies, deals, tickets, etc. These APIs are precision tools, and here's when it’s best to use them:

Direct Access to a Specific Object

When you know exactly which object you need to interact with, object-specific APIs offer a direct path to that data. They're optimized for CRUD (Create, Read, Update, Delete) operations on individual object types, making them faster and more efficient for these tasks.

Simple, Straightforward Queries

If your search is straightforward, such as retrieving all contacts with a certain property value, object-specific APIs are the way to go. They're simpler to use for basic queries and often require less setup than a search API call.

High-Volume Operations on a Single Object Type

When you're working with a large volume of operations on a single object type, object-specific APIs can be more performant. They allow you to streamline your interactions with the CRM and can handle bulk operations effectively.

Helpful Tips for API Selection

To make the most of HubSpot's APIs, here are some helpful tips:

  • Assess Your Needs: Before choosing an API, clearly define what you need to achieve. This will guide you toward the right API for the job.
  • Consider Performance: Consider the scale of your operations and choose the API that offers the best performance for your specific use case.
  • Read the DocumentationHubSpot's API documentation is comprehensive. Make sure to read it thoroughly to understand the capabilities and limitations of each API.
  • Test and Iterate: Don't be afraid to experiment. Sometimes, the best way to understand which API fits your needs is to try them out and iterate based on your findings.


Choosing between the CRM Search API and object-specific APIs in HubSpot boils down to the scope and specificity of your data interaction needs. Use the CRM Search API for complex, broad searches, and opt for object-specific APIs for direct, high-performance interactions with known object types.

By understanding the strengths of each API, you can ensure that your integration with HubSpot is as efficient and effective as possible. Happy data hunting!