Include serverless functions in projects (BETA)

Serverless functions allow you to write server-side code in JavaScript that runs on HubSpot. Because HubSpot runs the function, you don't need to manage your own server. 

In the context of HubSpot projects, serverless functions provide the core functionality for your private apps and extensions. In the project file structure, serverless functions consist of a folder that ends in .functions, one or more JavaScript files that export a main function, and a serverless.json file that registers and configures your functions.


To view example projects that use serverless functions, check out HubSpot's example extension library on GitHub.

Types of serverless functions

There are two types of serverless functions you can create, which you'll define in the serverless.json file.

  • API endpoint function: a serverless function that creates public API endpoints available under the domains connected to your HubSpot account. If an API call requires authentication, you can either use the private app's access token or include a secret containing an API key.
// A serverless.json file configured // for an API endpoint function { "runtime": "nodejs12.x", "version": "1.0", "endpoints": { "path/to/endpoint": { "file": "githubUserFunction.js" } } }
  • App function: a serverless function that is used by a private app extension, and only executes within HubSpot when the extension needs it. This type of function cannot be accessed publicly, and is typically referenced by name in other project config files. Learn how to authenticate app functions with the private app's access token or a secret containing an API key.

Please note: app functions have a response limit of 2 seconds. Any functions that take longer than this limit to execute will fail.

// A serverless.json file configured // for an app function { "runtime": "nodejs12.x", "version": "1.0", "appFunctions": { "weatherCard": { "file": "weather.js" } } }

Create a serverless function

To create a serverless function that provides functionality for your app or extension, you'll first need to create the JavaScript file that provides the functionality.

Each serverless function exports a main function that gets called when HubSpot executes it. The function receives two arguments:

  • context: an object that contains data that varies depending on how the function is being used.
  • callback: a callback function that should be called when the function's task is completed. This allows for asynchronous operations, such as making HTTP requests.

Below is an example of a function that returns a 200 status code and a Hello World message through a callback:

//helloWorld.js exports.main = function(context, callback) { callback({ statusCode: 200, body: {message: "Hello World"} }); }

Configuring a serverless function

For the serverless function JavaScript to run, you'll need to configure the serverless.json file. You can configure the following properties in the file:


The runtime environment. HubSpot supports Node.js version 12 ("nodejs12.x").


The version of HubSpot's serverless function schema. The current version is 1.0 ("1.0").


Values used for authentication, such as API keys. This value refers to the name of the secret, no its value. Do not put secret values directly in this file.


Configuration variables passed to the execution function as environment variables at runtime. You might use this to add logic for using a testing version of an API instead of the real thing based on an environment variable.


Use this property to create public API endpoints under the domains connected to your HubSpot account. See below for more information.


Use this property to reference the serverless function as a part of an app extension. Learn more about appFunctions.

Authenticate HubSpot API calls

When developing a private app with projects, each private app comes with a private access token that you can use to authenticate calls to HubSpot's APIs.

For example, when building a CRM card with Node.js, you'll first include the HubSpot node API client, then instantiate it within exports.main within the CRM card JavaScript file:

// Include HubSpot node API client const hubspot = require('@hubspot/api-client'); exports.main = async (context = {}, sendResponse) => { // instantiate HubSpot node API client const hubspotClient = new hubspot.Client({ accessToken: context.secrets.PRIVATE_APP_ACCESS_TOKEN }); //your function };

You can then configure the rest of the function using Node.js. For example, the following code would create a serverless function that retrieves a specific contact by ID using the contacts API:

// Example crm-card.js file // Include HubSpot node API client const hubspot = require('@hubspot/api-client'); exports.main = async (context = {}, sendResponse) => { // instantiate HubSpot Node API client const hubspotClient = new hubspot.Client({ accessToken: context.secrets.PRIVATE_APP_ACCESS_TOKEN }); // Defines the first section of the CRM card const demoObject = { objectId: 1, title: "Sample project custom CRM card", desc: "This card will retrieve data on the contact record." }; try { // Defines variables for API endpoint and response data const resp = await hubspotClient.crm.contacts.basicApi.getById("609051"); const data = resp.body; // Defines how the returned data will be displayed sendResponse({ results: [ demoObject, { objectId: 2, title: "This serverless function will retrieve a specific contact by ID.", desc:, }, ] }); } catch (error) { console.error(error); } };

To get started, you can find Node.js code snippets on the Endpoints tabs of HubSpot's API docs.

Including secrets in a function

If a function requires authentication, you can use a secret to securely store and use tokens, such as API keys. HubSpot will only decrypt a secret and make it available for a function that's been configured to use it. You can also use the private app's access token to authenticate API calls.

Please note: to limit exposure of a secret, it's strongly recommended to never include it in console statements to prevent it from being recorded in logs.

To add a secret to HubSpot, use the secrets add CLI command. Once you've added a secret to HubSpot, you'll then need include it in the definition of the endpoint or appFunction field in the serverless.json configuration file.

// serverless.json { "runtime": "nodejs12.x", "version": "1.0", "endpoints": { "path/to/endpoint": { "file": "githubUserFunction.js", "secrets": ["GITHUB_ACCESS_TOKEN"] } } }

The githubUserFunction.js file called within serverless.json can be configured as follows:

//githubUserFunction.js const axios = require('axios'); const ACCESS_TOKEN = process.env.GITHUB_ACCESS_TOKEN; exports.main = async function(context, sendResponse) { const response = await axios.get('', { headers: { 'Authorization': `token ${ACCESS_TOKEN}` } }); sendResponse({ statusCode: 200, body: { user: } }); };

Including NPM dependencies in a function

By default, HubSpot provides a small number of NPM dependencies in addition to the Node.js standard library. To add your own dependencies, you can list the package in dependencies within the package.json file. When the app is built, dependencies will be bundled with your function code. All dependencies must be published to NPM and be public.

For example, if you wanted to add the lodash library in a serverless function, you would first update package.json to include the dependency:

// package.json { "name": "app.functions", "version": "1.0.0", "description": "", "dependencies": { "lodash": "^4.17.21", } }

Then, at the top of your serverless function JavaScript file, you would require the lodash dependency:

// myFunction.js const _ = require('lodash'); exports.main = function(context, sendResponse) { const objectA = {}; const objectB = {}; const equal = _.isEqual(objectA, objectB); sendResponse({ statusCode: 200, body: { isEqual: equal } }); }

Debug a serverless function

Log messages are produced every time HubSpot executes a serverless function. Below, learn how to access logs in HubSpot and locally using the CLI.

In-app debugging

In HubSpot, you can view a serverless function's log history, including both successful requests and errors. When a CRM card fails to load, HubSpot will also display an error message in the card on the CRM record that links to that app's CRM card logs. 


To access a serverless function's logs in HubSpot:

  • In your HubSpot account, navigate to CRM Development.
  • In the left sidebar menu, navigate to Private apps.
  • Select the private app that contains the serverless function.
  • Click the Logs tab, then the CRM cards tab to view serverless function logs.
  • To view logs for a specific request, use the search bar to search by request ID, or click a request


You can also include console.log() in your serverless function code for debugging purposes, then view its output in the function log details sidebar.


Local debugging

Log messages are produced every time HubSpot executes a serverless function. To view a serverless function's logs for both API endpoint and app functions in the CLI, run the hs project logs command. This guide you through selecting the project, app, and function name or endpoint to get logs for. Learn more about using the hs project logs command.

There are two types of log messages produced:

  • Log messages that record the execution of a function, along with its status and timing. For example: 2021-04-28T19:19:21.666Z - SUCCESS - Execution Time: 279ms
  • Log messages that are produced through console statements in the function code. For example, your serverless function JavaScript might include:
// helloWorld.js exports.main = function(context, sendResponse) { console.log('Log some debug info'); console.error('An error occurred'); sendResponse({ statusCode: 200, body: {message: 'Hello World'} }); }

A log output for the above code would then produce the following:

2021-04-28T19:15:13.200Z    INFO   Log some debug info

2021-04-28T19:15:14.200Z    ERROR    An error occurred

Was this article helpful?
This form is used for documentation feedback only. Learn how to get help with HubSpot.