Searchable smart collection with records fetched from hubspot API

Please be sure of your agent type and version and pick the right documentation accordingly.

This is the documentation of the forest-express-sequelize and forest-express-mongoose Node.js agents that will soon reach end-of-support.

forest-express-sequelize v9 and forest-express-mongoose v9 are replaced by @forestadmin/agent v1.

Please check your agent type and version and read on or switch to the right documentation.

Searchable smart collection with records fetched from hubspot API

Context: Create a smart collection fetching the 10 first companies records from hubspot or the ones matching a search criteria

First step is to declare the collection and the fields that should be expected to be found for this collection.

const Liana = require('forest-express-sequelize');
const models = require('../models');

Liana.collection('hubspot_companies', {
  isSearchable: true,
  fields: [
      field: 'id',
      type: 'Number',
      field: 'name',
      type: 'String',

Next step is to define the logic to retrieve the data of the smart collection in a routes/your-model.js file.

You first need to set variables according to the context to ensure the query follows the UX (nb of records per page, index of the page you're on, search performed or not)

You then need to define a serializer adapted to the format of the data that will be passed and the expected fields of the collection.

Finally you need to implement the API call, serialize the data obtained, filter depending on the search performed and return the payload.

NB: I used the superagent module for the API call

const Liana = require('forest-express-sequelize');
const express = require('express');
const router = express.Router();
const models = require('../models');
const P = require('bluebird');
const JSONAPISerializer = require('jsonapi-serializer').Serializer;
const superagent = require('superagent');

  (req, res, next) => {
    // set pagination parameters when exist (default limit is 250 as it is the max allowed by Hubspot)
    let limit = 250;
    let offset = 0; ? (limit = parseInt( : limit;
      ? (offset = (parseInt( - 1) * limit)
      : offset;

    // set search terms when exist
    let search = null; ? (search = : search;

    // define the serializer used to format the payload
    const hubspotCompaniesSerializer = new JSONAPISerializer(
        attributes: ['name'],
        keyForAttribute: 'underscore_case',
        id: 'companyId',
        transform: function (record) {
 = record['properties']['name']['value'];
          return record;

    // implement function to call hubspot API and return companies
    async function getCompanies() {
      return (hubspot_companies = await superagent
        .then((response) => {
          // parsing the answer from the API
          companiesJSON = JSON.parse(response.res.text).companies;
          // serializing the companies to comply with the format expected by the Forest server
          serializedCompanies =
          // return all data or data with a name containing the searched terms from the companies fetched
          if (search) {
              function (item) {
            return serializedCompanies;
          } else {
            return serializedCompanies;

    async function sendCompaniesPayload() {
      let hubspotCompanies = await getCompanies();
      // defining the count of companies fetched
      let count =;
      return res.send({ ...hubspotCompanies, meta: { count: count } });


module.exports = router;

Last updated