Query HubSpot data using GraphQL (BETA)

Last updated:

This functionality is in beta and requires your account to be ungated. You can request access by submitting this form. By participating in this beta you agree to HubSpot's Developer Terms and Developer Beta Terms. Please note that this functionality is currently under development and is subject to change based on testing and feedback.

 
APPLICABLE PRODUCTS
  • CMS Hub
    • Professional or Enterprise

GraphQL is a data query language that provides a unified way to access your HubSpot CRM data to create personalized and data-driven experiences for your website visitors.

Below, learn more about the benefits of using GraphQL, how to structure and test GraphQL queries, and how to use the data from a query in a theme or module. If you want to see an example of how GraphQL queries work in practice, check out this tutorial.

Advantages of using GraphQL

The GraphQL API provides a single, unified way to fetch data from different data sources to power your website pages, instead of having to process and aggregate data from disparate REST API endpoints.

You can specify the data within GraphQL queries, which allows you to decouple how you're fetching data from the presentational layer of your template and module code. You can then include queries as part of your theme, or connect them directly to your modules, templates, and pages.

GraphQL schema and queries

In HubSpot, the GraphQL schema describes the data sources you're fetching from and the underlying data types available to your HubSpot account. This schema is auto-generated and will automatically update if you add custom properties, create custom objects, or associate object types.

You can construct GraphQL queries to fetch data by traversing the schema from your HubSpot account. This approach allows you to specify the data you need for a given page on your website.

GraphQL query structure

Each GraphQL query consists of a tree of nested fields: 

GraphQL
query MyQuery {
  # Root query field
  CRM {
    # Child fields
    contact_collection {
      items {
        # Properties
        email
        firstname
        lastname
      }
    }
  }
}
  • Root query field: the top-level field of your query that represents your data source. Currently, the only supported data source is data from your HubSpot CRM.
  • Child fields: child fields specify which CRM data types you want to fetch, along with any associated properties. 
    • Both standard and custom objects are supported as data types, along with some other HubSpot assets such as meetings, marketing events, quotes, and tickets. You can query for an instance of a data type via an instance query field, such as an individual contact by its ID, or you can fetch a list of instances of a particular data type via a collection query field.
    • Any properties you need for each data type can be included by entering each property as a nested child field of that data type.

Create and run a GraphQL query

You can test queries by using GraphiQL, which is an open-source tool that allows you to run queries interactively and explore which fields are available.

  • In your HubSpot account, navigate to the GraphiQL tool.
  • In the left pane, create and edit your query by specifying the objects and their associated fields you'll need for your website pages.

graphiql-initial-view

Compose your query

Within the CRM root query field, enter a data type as a child field to retrieve a single object instance, or enter a data type followed by _collection to retrieve a list of objects of that type. You can provide arguments to a query field to fetch a single object or filter a collection of objects.

  • Fetch a single instance: if you're fetching a single instance like an individual contact record, specify one of the object's properties and its associated value by including the property's name as the uniqueIdentifier, and the property's value as the uniqueIdentifierValue. For example, the following query would fetch a contact with an ID of 753:
GraphQL
query filteredContact {
   CRM {
    contact(uniqueIdentifier: "id", uniqueIdentifierValue: "756") {
       email
     }
   }
}
  • Fetch and filter a collection: to fetch a collection of instances, add items as a child field. To filter the objects in the response, include the filter argument, then provide a map of filter operators to their associated values. A filter operator consists of the property you want to filter by, followed by a suffix. For example, the query below would fetch and filter a collection of contacts with hubspot.com email addresses:
GraphQL
query filteredContactCollection {
   CRM {
    contact_collection(filter: {email__contains: "hubspot.com"}) {
       items {
         email
       }
     }
   }
}

After you've added a data type to your query, you can specify the properties, associations, or metadata you need by adding child fields:

  • Add properties to fetch: enter the internal name of a property to include it in the response of your query. Both default and custom properties are supported.
  • Include associations to other data types: you can also add a collection of a instances of a data type associated with the parent data type, such as the companies associated with a contact. To add data from an associated data type:
    • Include associations as a child field of the original data type you entered.
    • As a child field of associations, enter the association you want to include by following the naming scheme of {ASSOCIATED_DATA_TYPE}_collection__{LABEL}.
      • The associated data type can be a built-in association with a standard object, or an association with a custom object. Any associations to custom objects will be prefixed by p_.
      • The association's label is either __primary or __general for associations between standard objects. If you're including an association to a custom object, the label is formatted as:  __{ASSOCIATED_DATA_TYPE}_to_{PARENT_DATA_TYPE}.
      • For example, if you had a custom object named House associated with the contact object, the association you'd include in your query would be p_house_collection__house_to_contact.
    • Add items as a child field of your association, then include any properties you need from each item in the collection.
GraphQL
query contactsWithAssociatedCompany {
  CRM {
    contact_collection {
      items {
        firstname
        lastname
        associations {
          company_collection__primary {
            items {
              name
              address
            }
          }
        }
      }
    }
  }
}

Run and refine your query

  • To view all available data types, properties, and filters, click Explorer at the top of the page to toggle the Explorer view, which will list all available data types and their associated properties. 
    • Click a data type to automatically add it to your query and view all its associated properties.
    • Select the checkbox next to a property to add it to your query.
    • If you're writing a query and you're entering an argument for one of your fields, the Explorer pane will auto-populate a list of available filters.
  • When you're ready to test a query, click the play icon at the top of the page. The query's response will appear in the right pane.

run-query-in-graphiql-1

 

Query arguments and filters

You can provide arguments to a collection field in your query to filter, order, or paginate the objects returned in the response. The table below lists the supported arguments:

Use this table to describe parameters / fields
ArgumentTypeDescription
filter
Input type

A set of filter options to apply on the collection items

limit
Integer

The maximum number of items to fetch. By default, 10 items are returned. The maximum is 1000.

orderBy
Enum array

The ordering to apply on the fetched items. The default ordering is ascending by the item's id.

offset
Integer

The index from where to start fetching items. The default is 0. When paginating results, the next offset is returned in the response.

Create a filter by combining a HubSpot property with a suffix that corresponds to a logical or mathematical operator (e.g., email_contains or name_eq). The supported operators are shown in the table below:

Filter Postfix Field types Example
equal _eq String, Number, Timestamp email_eq: “user@domain.com”
not equal _neq String, Number, Timestamp firstname_neq: “Bob”
less than _lt Number, timestamp price_lt: 45
less than or equal _lte Number, Timestamp started_lte: 1633606374
greater than _gt Number, Timestamp salary_gt: 60000
greater than or equal _gte Number, Timestamp birthdate_gte: 1633606374
contains _contains String name_contains: “Inc.”
does not contain _not_contains String address_not_contains: “Miami”
in given list _in String, Number, Timestamp firstname_in: [“Victoria”, "John", "Katie"]
not in given list _not_in String, Number, Timestamp status_not_in: [“rejected”, "pending"]
has value / does not have value _null Any type email_null: false

Use data from your query in your website pages

Once you're familiar with how GraphQL works and you've written a query that specifies the data you'll need, you can use the query in your theme.

  • Save your query in a file with the .graphql extension. It's recommended you keep GraphQL query files in a separate directory at the root of your theme to keep them organized and make them easier to reference with a relative path.
  • Upload a theme that includes the query file using the HubSpot CLI tools, or through the design manager in your HubSpot account. 

Once you've uploaded your GraphQL files, you can bind them to a module or template, which will make the query's data available to the rendering context of the module or template.

Bind a data query to a template

To bind a GraphQL query to a template so you can reference the data in your code, add a dataQueryPath template annotation and provide the path to the associated GraphQL query file. You don't need to include the file's .graphql extension in the path.

For example, if you want to bind a query file to a template that renders the query's results on the page, the top of your template's code would include the following:

HTML
<!--
  templateType: page
  isAvailableForNewContent: true
  label: Contact profile page - GraphQL
  dataQueryPath: ../data-queries/contact_info
-->

You can then reference the response to the data query in your template and module code from the data_query variable in HubL. The example below defines a HubL variable to store available roles:

HubL
{% set contactData = data_query.data.CRM.contact %}

Bind a data query to a module

You can also bind a GraphQL query directly to a module by including a data_query_path parameter in your module's meta.json file. It's recommended you define your module within a modules directory at the root of your theme to make it easier to reference your query with a relative path.

  • Using the HubSpot CLI tools, fetch the module's directory. 
  • Add the data_query_path parameter and specify the path to the associated GraphQL query file, relative to the location of the meta.json file. For example, if the query file is in a data-queries directory at the root of your theme, your meta.json file would include the following:
JSON
// meta.json
{ 
  "data_query_path": "../../data-queries/contactsQuery" 
}
  • Upload the updated meta.json file to your HubSpot account.

You can then reference the response of your query in your module code using the data_query variable. The example below defines a HubL variable to store the queried data for a collection of contacts:

HubL
{% set contactCollectionData = module.data_query.data.CRM.contact_collection %}

Pass dynamic context into a query

If your query requires context that is dynamic to a given request, such as data from a contact who's visiting one of your pages, you can pass HubL variables in your GraphQL queries. 

  • First, define the variable in a single line comment at the top of your query using the # character. The convention for GraphQL variable names is to prefix them with a $ character. For example, to define a variable for the ID of a contact:
# $contact_id = "{{ request.contact.contact_vid || ''}}"
  • Include your variable and its type as a parameter in your query definition. If you want your variable to non-nullable, add an ! after its type. To pass the $contact_id variable above into a query to show contact info for a given contact, your query definition would begin with:

query contact_info($contact_id: String!)

  • You can then reference your variable and provide it as an argument to any of the filters in your query. Using the $contact_id variable from above, the query below would provide the first name, last name, and email of a contact visiting a page:
GraphQL
# label: "Contact info page"
# description: "Show a contact's name and email"
# $contact_id: "{{request.contact.contact_vid }}"
query contact_info($contact_id: String!) {
  CRM {
    contact(uniqueIdentifier: "id", uniqueIdentifierValue: $contact_id) {
      _metadata {
        id
      }
      firstname
      lastname
      email
    }
  }
}
  • You can also pass URL query string parameters as arguments to your GraphQL query using the request.query_dict HubL variable. For example, if you have a page URL that contained /contacts?location=Boston&department=marketing, and wanted to use the URL query parameters in your GraphQL query to filter contacts by location and department, you could use the following GraphQL query:
GraphQL
# label: "Contact listing page with filters"
# description: "Filter contacts by location and department"
# $location: "{{ request.query_dict.location  || ''}}"
# $department: "{{ request.query_dict.department || ''}"
query contact_listing_page($location: String!, department: $String) {
  CRM {
    contact_collection(filter: {location__eq: $location, department_eq: $department) {
      items {
        _metadata {
         id
        }
        firstname
        lastname
        email
      }
    }
  }
}

Use a GraphQL query in an API request

To use a GraphQL query in your integration, a Jamstack site, or in a custom code action in the workflows tool, you can include it in an authenticated POST request to the /collector/v3/graphql endpoint.

In the request body, include the operationNamequery, and any variables you want to pass to the query.

Use this table to describe parameters / fields
ParameterTypeDescription
operationName
String

A label for the query included in the request

query
String

The GraphQL query to execute

variables
JSON object

A JSON object containing any variables you want to pass to the query

For example, if you created a House custom object, and you wanted to query for a collection of House records in Miami, the request body would contain:

JSON
// POST request body to https://api.hubapi.com/collector/v3/graphql?hapikey=xxxx-xxxxx-xxxxx-xxxxx-xxxxx
{
  "operationName": "houses"
  "query": "query houses ($city: String) { CRM
            {house_collection(filter: {city__eq: $city}) { items {
            asking_price bedrooms bathrooms city}}}}",
  "variables": {"city": "Miami"}
}

Example return payload:

JSON
{
  "data": {
    "CRM": {
      "house_collection": {
        "items": [
          {
            "asking_price": 800000,
            "bedrooms": 3,
            "bathrooms": 2,
            "city": "Miami"
          }
          {
            "asking_price": 940000,
            "bedrooms": 2,
            "bathrooms": 2,
            "city": "Miami"
          }
        ]
      }
    }
  }
}

Was this page helpful? *
This form is for feedback on our developer docs. If you have feedback on the HubSpot product, please share it in our Idea Forum instead.