HubSpot CRM API: filtering contacts and retrieving specific properties

I’m working with the HubSpot Contacts API using PHP and running into some issues. I need help with two main things:

  1. Applying filters to contact searches
  2. Specifying which contact properties to return

When I try to include both filtering and property selection in my request, I get this error: Cannot deserialize instance of java.util.LinkedHashMap out of START_ARRAY token

Here’s my current code:

$endpoint = 'https://api.hubapi.com/crm/v3/objects/contacts?limit=100&archived=false&hapikey=your_api_key_here';

// Initialize cURL
$curl = curl_init($endpoint);

// Request payload
$requestData = array(
    'properties' => array(
        'given_name', 'family_name', 'email_address'
    ),
    'filterGroups' => array(
        [
            'propertyName' => 'given_name',
            'operator'=> 'EQ',
            'value'=> 'John'
        ]
    )
);
$jsonPayload = json_encode($requestData);

echo $jsonPayload;

// Configure cURL options
curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonPayload);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

// Send request
$response = curl_exec($curl);
curl_close($curl);

If I remove the ‘properties’ part from my request, I get a response but it only shows default fields and not the specific ones I want. The filtering also doesn’t seem to work properly even though I know there are contacts matching my criteria.

What’s the correct way to structure this API call?

the issue is your endpoint - you can’t send json data to the regular contacts endpoint. use /crm/v3/objects/contacts/search instead and make sure your filterGroups structure is right. also, double-check those property names since hubspot’s internal names are different from what you see in the UI.

You’re mixing GET and POST request syntax. For filtering contacts, use POST with the /crm/v3/objects/contacts/search endpoint instead of the regular GET endpoint. Here’s what to change: $endpoint = 'https://api.hubapi.com/crm/v3/objects/contacts/search'; $requestData = array('properties' => array('given_name', 'family_name', 'email_address'), 'filterGroups' => array(array('filters' => array(array('propertyName' => 'firstname', 'operator' => 'EQ', 'value' => 'John')))), 'limit' => 100); Two key changes: wrap your filter structure in a filters array, and use firstname instead of given_name for the property name. HubSpot’s internal property names are different from what you see in the UI. Also, put your API key in the Authorization header instead of the URL - it’s more secure.

Your code has some structural issues causing that deserialization error. You’re sending JSON data to an endpoint that won’t accept it in that format. The main problem is your filterGroups structure - you need to nest your filter inside a ‘filters’ array within each filter group. You’re missing this wrapper layer. Also, HubSpot property names don’t match what you see in the UI. Use ‘firstname’ instead of ‘given_name’, ‘lastname’ for ‘family_name’, and ‘email’ for ‘email_address’. I ran into the same issues migrating from v1 to v3 API last year. The search endpoint handles complex queries way better than trying to build URL parameters. Don’t forget proper error handling in your cURL setup - HubSpot’s error messages are actually pretty specific about what’s wrong with your request structure.

You’re sending a POST request to a GET endpoint - that’s why it’s failing. The /crm/v3/objects/contacts endpoint wants parameters in the URL, not the body. Switch to /crm/v3/objects/contacts/search and keep your current request structure. If you’d rather stick with GET, build the URL like this: https://api.hubapi.com/crm/v3/objects/contacts?properties=firstname,lastname,email&limit=100. But honestly, complex filtering with GET gets messy fast - the search endpoint works better. Just make sure you’re using HubSpot’s internal property names: ‘firstname’ not ‘given_name’, ‘lastname’ not ‘family_name’, and ‘email’ not ‘email_address’.