Getting started with serverless functions

Last updated:

Please note: if you're building a serverless function as a part of a developer project, visit the developer projects serverless function documentation instead. The documentation below is for building serverless functions outside of the developer project platform.

  • Content Hub
    • Enterprise

Serverless functions provide a way to write server-side code that interacts with HubSpot and third-party services through APIs.  APIs requiring authentication are not safe for the front-end of a website, as your credentials would be exposed.

 Serverless functions can act as an intermediary between your front-end and back-end services that require authentication. With serverless functions, developers don’t need to spin up and manage new servers. Serverless functions require less overhead and as a result they are easier to scale as a business grows. We have a high level overview of what HubSpot serverless functions are and how they work, we recommend reading through before doing this tutorial.

This tutorial will guide you through the creation of your first serverless function.

You will create a serverless function folder, set up your configuration folder, create a function and get a response from it.

What you should do before taking this tutorial:

1. Create a project folder

Open your hubspot.config.yml file, and make sure your defaultPortal is set to either your CMS Developer Sandbox account or an account with CMS Hub Enterprise.

On your computer, in the folder that contains your hubspot.config.yml file, create a serverless-tutorial folder. This folder will contain all of our files, both the functions themselves and a template which will use the function. 

In your terminal run the watch command:

hs watch serverless-tutorial serverless-tutorial

This will cause any edits to this folder to result in uploads to the design manager. Since the folder currently has no content, this command will simply state Watcher is ready and watching.

2. Create a functions folder

Inside of the serverless-tutorial folder create a my-first-function.functions folder.
This is similar to custom modules folders which end in .module, .functions serves to communicate that folder contains serverless functions. Files stored in this folder are not publicly accessible.

Because this folder is currently empty the watch command you have running will not create this folder in the Design Manager yet.

3. Create a configuration file

Create a new file in your my-first-function.functions folder, name it serverless.json. serverless.json is a required file contained within a .functions folder. It serves as a configuration file for serverless functions. Defining the runtime environment, serverless function version, and available endpoints. For a rundown of everything that gets defined in this file, see our serverless reference.

If you created and saved the file empty, you'll receive an error message in your terminal stating you can't upload an empty serverless.json file. That's okay, to ignore because you're going to add that code and then save it - triggering a new upload that will suceed.

Paste the code below into your serverless.json:

// place this in your serverless.json file, without this comment { "runtime": "nodejs18.x", "version": "1.0", "endpoints": { } }

Save the file.

Keep this file open in your code editor, we will be coming back to it.

Because watch is running, if you refresh your design manager you will now see your serverless-tutorial and my-first-function.functions folders and your new serverless.json file. 

4. Create a function file

Create a new file in your my-first-function.functions folder, name it congratulation.js

This is the actual function file, the file that will execute and perform a task.

Paste in the code below:

exports.main = (context, sendResponse) => { // your code called when the function is executed const functionResponse = "Congrats! You've just deployed a Serverless Function." // sendResponse is a callback function you call to send your response. sendResponse({body: functionResponse, statusCode: 200}); };

This serverless function when executed returns a string "Congrats! You just deployed a Serverless Function." and a status code of 200, indicating success.

In a real world scenario it is likely you might use APIs or perform some calculations you don't want public. You would return the result of those calculations or, a simple status code based on how the success of your API transactions.

You are not done yet, there is no way to execute this function just yet.

5. Register your function in your serverless.json

Open your serverless.json file again. In your file find your "endpoints" object.

Update the object to look like this:

// update the endpoints object in your serverless.json to reflect this object. "endpoints": { "congratulation": { "method": "GET", "file": "congratulation.js" } }

The endpoints object contains a "congratulation" object. "congratulation" is the endpoint you're creating. The endpoint's name is what defines the path that you will use to call your serverless function.

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

These functions can be accessed  at: 


In the case of this "congratulation" endpoint you've created, it will be 


Because of this it is generally a good idea to name your endpoint similarly to your function file's name, and both should be named based on the information they act against, not the action taken against that information. You should use the HTTP method or methods for communicating the type of action you are making against that information. The "method" parameter defines the HTTP method's your function supports. It can be a single string or an array of strings denoting the methods the function supports.

6. Test your function

The simplest way to test a GET request to your serverless function is to go to your endpoint's URL directly in the browser.

Replacing with your HubSpot site's domain.

You should see "Congrats! You just deployed a serverless function".

Success, you did it!

If you do not get that response, start from the top of this tutorial carefully reading each step and verifying the code. It is likely instructions in step 4 or 5 were not followed correctly.

For more complicated requests it's helpful to use a tool like Postman. Postman makes it easier to test and debug APIs. A handy feature for front-end developers is it's code generation which can generate a starting point for your javascript call to your function.

7. Create a basic template calling your function

Using a new terminal window navigate into your serverless-tutorial folder using cd.

Run the following command in your terminal:

hs create template "test-function"

This creates a test-function.html file. Open this file in your code editor.

Above the </head> tag add <script></script>.

Copy the javascript below:

var requestOptions = { 'method': 'GET', 'headers': { 'Content-Type': 'application/json', } }; fetch("", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error));

HubSpot serverless functions only support the content type application/json. Leaving it out will result in an "Unsupported Media Type" error.

Inside of the script tag you created earlier, paste your copied JavaScript code.

Change to your account's domain.

Save the file.

8. Create a page using the test-function.html template

In the design manager find your test-function.html file (you may need to refresh)

Right click the file, choose "create page".

Name your page "Test Function". Create page.

Click preview, preview in new window

Inspect the page by right clicking anywhere on the page and selecting "inspect".

If you did everything correctly you should see in your console the congratulations message.

Congratulations, you've called your serverless function from within a HubSpot CMS page. 

While this tutorial has you call the serverless function at the template level, you can call serverless functions anywhere that you can add JavaScript on your CMS hosted site. The most common place you might do this is within your custom modules.

Debugging your serverless function

At this stage your serverless function should work fine. The more complicated your function gets, the harder it is to troubleshoot. Just like the console in your browser is useful for debugging javascript on your front-end, you can get similar logs for your serverless functions using hs logs. Check out the local development reference for more information on this command.

hs logs <endpoint-name> --follow

What did you do?

You created a serverless function folder, with a serverless.json configuration file, and function file named congratulation.js. You used "GET" to get congratulations text from the serverless function. You used javascript to make a call to your serverless function from a page on the HubSpot CMS.

Now that you understand how the configuration file, function file, and .functions folder relate, the CLI has a handy command you can use to create your functions faster next time.

hs create function <function name>

This function creates a .functions folder, serverless.json file and a function file with the names you provide.

Where to go from here?

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