Serverless functions reference

Last updated:
APPLICABLE PRODUCTS
  • CMS Hub
    • Enterprise

This document walks through the files found inside of a serverless .functions folder and serverless specific CLI commands.

See serverless functions for a high level overview.

Serverless.json

Your serverless.json file stores your configuration settings for functions inside of your .functions folder. This file is required for serverless functions to work. This file maps your functions to their endpoints.

The serverless.json file must be uploaded using the local development tools, it cannot be created in the Design Manager.

JSON
// serverless.json
{ 
  "runtime": "nodejs12.x",
  "version": "1.0",
  "environment": {
    "globalConfigKey": "some-value"
  },
  "secrets": ["secretName"],
  "endpoints": {
    "events": {
       "file": "function1.js",
	 "method":"GET"
    },
    "events/update": {
      "method": "POST",
      "file": "action2.js",
      "environment": {
        "CONFIG_KEY": "some-other-value"
      },
      "secrets": ["googleKeyName","otherkeyname"]
    }
  }
}
Use this table to describe parameters / fields
key Type Description
runtime
required
String

Runtime environment. Currently we support ‘nodejs12.x’ (Node.js version 12)

version
required
String

HubSpot serverless function schema version. (Current version 1.0)

endpoints
required
Object

Endpoints define the paths that are exposed and their mapping to specific JavaScript files, within your functions folder.

environment
Object

Configuration variables passed to the executing 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.

secrets
array

An API key is a secret. The secrets in the config file refers to the name of the secret not it’s value. Do not put secrets directly in this file, only reference secret names. 

Endpoints

Each endpoint can have its own environment variables and secrets. Variables specified outside of endpoints should be used for configuration settings that apply to all functions and endpoints.

JSON
"events/update": {
      "method": "POST",
      "file": "action2.js",
      "environment": {
        "configKey": "some-other-value"
      },
      "secrets": ["googleAPIKeyName","otherKeyName"]
    }

Endpoints have a couple unique keys.

Use this table to describe parameters / fields
key Type Description
method
String or array of strings

HTTP method or methods that the endpoint supports. Defaults to GET.

file
required
String

Path to JavaScript function file with the implementation for the endpoint.

Serverless functions are exposed through a path at your HubSpot CMS account’s domain.

These functions can be accessed  at: 

<https://www.example.com>/_hcms/api/<endpoint-name/path>

Replace <https://www.example.com> with your domain name. /_hcms/api/ is a reserved path for serverless functions, all of your endpoints exist inside this path. Replace <endpoint-name/path> with an endpoint name you specified in your serverless.json file.

Function file

Each function is created as a Node.js JavaScript file in a folder ending in .functions. In addition to the Node.js standard library, functions can leverage the request library to make HTTP request to HubSpot APIs and other APIs. 

A basic serverless-function.js file looks like:

Your function files must be uploaded using the local development tools, it cannot be created in the Design Manager.

JavaScript
// Require request library, to make API requests.
const request = require('request');
// Environment variables from your serverless.json
// process.env.globalConfigKey

//context = { params, body, secrets, accountId }
exports.main = (context, sendResponse) => {
  // your code called when the function is executed
  // secrets created using the CLI are available in context
  // context.secrets.secretName 

  //sendResponse is what you will send back to services hitting your serverless function.
  sendResponse({body: {message:"my response"}, statusCode: 200});
};

Context object keys

Context Object Keys
Parameter Description
accountId

The HubSpot account ID containing the function.

body

body is populated if the request is sent as a POST with a content type of application/json

contact

If the request is from a cookied contact, the contact object will be present with a set of basic contact properties. These additional properties will also be available:

  • vid: The contact’s visitor id
  • isLoggedIn: when using CMS Memberships, this will be true if the contact is logged into the domain
  • listMemberships: an array of contact list ids that this contact is a member of
header

Contains headers sent from the client hitting your endpoint. See headers.

params

params is populated with query string values plus any HTML Form-POSTed values. These are structured as a map with strings as keys and an array of strings for each value. content.params.yourvalue

secrets

API keys, accessible by name

Headers

Sometimes it can be helpful to have the headers of the client hitting your endpoint. We provide the following headers through context.header. This is similar to how you would access information through context.body.

Use this table to describe parameters / fields
header Description
accept

Communicates which content types expressed as MIME types, the client understands. See MDN.

accept-encoding

Communicates the content encoding the client understands. See MDN.

accept-language

Communicates which human language and locale is preferred. See MDN.

cache-control

Holds directives for caching. See MDN.

connection

Communicates whether the network connection stays open. See MDN.

cookie

Contains cookies by sent the client. See MDN.

host

Communicates the domain name and TCP port number of a listening server. See MDN.

true-client-ip

IP address of the end-user. See Cloudflare true-client-ip.

upgrade-insecure-requests

Communicates the clients preference for an encrypted and authenticated response. See MDN.

user-agent

Vendor defined string identifying the application, operating system, application vendor, and version. See MDN.

x-forwarded-for

Identifies the originating IP address of a client through a proxy or load balancer. See MDN.

Redirect by sending a header

You can perform a redirect from your serverless function by  sending a response with a location header and 301 statusCode.

JavaScript
sendResponse({
       statusCode: 301,
       headers: {
           "Location": "https://www.example.com"
       }
});

Secrets

API keys, and authentication information are referred to as secrets. Once added they are accessible through the payload. You can assign secrets available for specific endpoints to use by adding the "secrets" key to your serverless.json file. Secrets are managed through the HubSpot CLI using the following commands:

Do not return your secret's value through console logging or as a response. Doing so would expose your secrets in your logs or in front-end pages that call your serverless function.

Using serverless functions with the form element

When submitting serverless functions use javascript to handle the form submission, and use the "contentType" : "application/json" header in your request. Do not use the <form> elements action attribute.

CORS

Cross Origin Resource Sharing (CORS) is a browser security feature. By default browsers restrict cross-origin requests initiated by javascript. This prevents malicious code running on a different domain, from affecting your site. This is called the same-origin policy. Because sending and retrieving data from other servers is sometimes a necessity, the external server, can supply HTTP headers that communicate which origins are permitted to read the information from a browser.

You should not run into CORS issues calling your serverless function within your HubSpot hosted pages. If you do, verify you are using the correct protocol.

Getting this CORS error?
"Access to fetch at [your function url] from origin [page making request] has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."

Is your request to a different origin than the site calling it?

  • If the domain name is different, yes.
  • If using a different protocol(http, https), yes.

If using a different protocol, simply change the protocol to match and that will fix it. 

You can't HubSpot's Access-Control-Allow-Origin header at this time.



See MDN for further detailed CORS error troubleshooting.

Get requests

Get requests may be able to make CORS requests depending on the client. Do not make GET requests write anything, just return data.

Preloaded packages

HubSpot serverless functions currently come preloaded with a few packages to make building on HubSpot easier.

 

Updating/using newly supported preloaded packages in existing functions

At launch serverless functions only came preloaded with the request package. If you would like to use the latest supported version of a preloaded package, or want to use one of the packages that has been added. The easiest way to do that is to:

  1. clone/copy your function file
  2. change your function's endpoint in the serverless.json to point to your new function file. You can safely delete the old version.

How to include other packages

Sometimes you need to be able to load packages to make data manipulation or transfer easier. Right now the list of preloaded packages is small. You may have a need that the preloaded packages do not solve for. This doesn't mean you're completely out of luck.

The easiest solution is to use webpack to combine your node modules and have your bundled files be your function files.

Know your limits

Serverless functions are intended to be fast and have a narrow focus. That speed enables them to be perfect companions to the front-end of websites and apps, enabling a quick call and response. HubSpot serverless functions are limited to:

  • 50 secrets per account
  • 128MB of memory
  • 10 seconds of execution time
  • 60 function executions per minute
  • 600 seconds (10 minutes) of function execution time per minute. This means that in a single minute, 60 functions that complete in 10 seconds could run OR 600 function executions that complete in 1 second could run.
  • No more than 100 endpoints per HubSpot account
  • You must use contentType application/json when calling a function.

Functions that exceed those limits will throw an error. Execution count and time limits will return a 429 response. The execution time of each function is included in the serverless function logs.