> ## Documentation Index
> Fetch the complete documentation index at: https://developers.hubspot.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

---
id: 09638618-081d-4e40-a35a-24d5f76c897f
---

# Serverless functions reference (design manager)

> Reference information for serverless functions built with the design manager, including serverless.json, function files, endpoints, CLI commands, and managing packages.

export const SupportedProducts = ({marketing, sales, service, cms, data, commerce, marketingLevel, salesLevel, serviceLevel, cmsLevel, dataLevel, commerceLevel}) => {
  const translations = {
    description: "Requires one of the following products or higher.",
    productNames: {
      marketing: "Marketing Hub",
      sales: "Sales Hub",
      service: "Service Hub",
      cms: "Content Hub",
      data: "Data Hub",
      commerce: "Commerce Hub"
    },
    tiers: {
      free: "Free",
      starter: "Starter",
      professional: "Professional",
      enterprise: "Enterprise"
    }
  };
  const translateTier = tier => {
    if (!tier) return '';
    const lowerTier = tier.toLowerCase();
    return translations.tiers[lowerTier] || tier;
  };
  const products = [{
    name: marketing ? translations.productNames.marketing : '',
    level: translateTier(marketingLevel),
    icon: "https://mintlify-assets.b-cdn.net/Icons/marketing-bolt.svg",
    alt: "Marketing Hub"
  }, {
    name: sales ? translations.productNames.sales : '',
    level: translateTier(salesLevel),
    icon: "https://mintlify-assets.b-cdn.net/Icons/sales-star.svg",
    alt: "Sales Hub"
  }, {
    name: service ? translations.productNames.service : '',
    level: translateTier(serviceLevel),
    icon: "https://mintlify-assets.b-cdn.net/Icons/service-heart.svg",
    alt: "Service Hub"
  }, {
    name: cms ? translations.productNames.cms : '',
    level: translateTier(cmsLevel),
    icon: "https://mintlify-assets.b-cdn.net/Icons/content-play.svg",
    alt: "Content Hub"
  }, {
    name: data ? translations.productNames.data : '',
    level: translateTier(dataLevel),
    icon: "https://developers.hubspot.com/hubfs/Knowledge_Base_2023-24-25/subscription_key_icons/operations_icon.svg",
    alt: "Data Hub"
  }, {
    name: commerce ? translations.productNames.commerce : '',
    level: translateTier(commerceLevel),
    icon: "https://developers.hubspot.com/hubfs/Knowledge_Base/subscription_key_icons/commerce_icon.svg",
    alt: "Commerce Hub"
  }].filter(product => product.name && product.level);
  if (products.length === 0) return null;
  return <div>
      <div className="text-sm mb-2">{translations.description}</div>
      <div className={`grid ${products.length === 1 ? 'grid-cols-1' : 'grid-cols-2'} gap-1.5`}>
        {products.map((product, index) => <div key={index} style={{
    display: 'flex',
    alignItems: 'center'
  }}>
            <img src={product.icon} alt={product.alt} className="w-3.5 h-3.5 mr-1.5 mt-2.5 mb-2.5 flex-shrink-0 align-middle" />
            <span className="font-medium mr-1 text-sm">{product.name} -</span>
            <span className="text-sm">{product.level}</span>
          </div>)}
      </div>
    </div>;
};

<Accordion title="Supported products" defaultOpen="true" icon="cubes">
  <SupportedProducts cms={true} cmsLevel="enterprise" />
</Accordion>

<Warning>
  **Please note:**

  This page contains reference information for serverless functions built using the design manager. Historically, this is the original way to build serverless functions for your CMS pages, and is still supported. However, moving forward it's recommended to [build and deploy serverless functions with HubSpot developer projects](/cms/start-building/features/serverless-functions/getting-started-with-serverless-functions). Project-based serverless functions can include third-party dependencies, and have more direct access to authentication through private app access tokens.
</Warning>

<ProductTier tiers={['cms-enterprise']} />

In this article, learn about the files found inside of a [serverless `.functions` folder](/cms/start-building/features/serverless-functions/overview#serverless-function-folders) and the CLI commands you can use with serverless functions.

For a high-level overview of serverless functions, see the [serverless functions overview](/cms/start-building/features/serverless-functions/overview).

For more information about building serverless functions with projects for [JavaScript rendered modules and partials](https://github.hubspot.com/cms-js-building-block-examples/), see the [developer projects documentation](/cms/reference/serverless-functions/serverless-functions-in-projects).

## Serverless.json

In the `.functions` folder, the `serverless.json` file stores the serverless function configuration. This is a required file, and maps your functions to their [endpoints](#endpoints).

```json theme={null}
{
  "runtime": "nodejs20.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"]
    }
  }
}
```

| key           | Type   | Description                                                                                                                                                                                                                                                                                                  |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `runtime`     | String | The runtime environment. Supports [Node.js](https://nodejs.org/en/about/) v20 (`nodejs20.x`).                                                                                                                                                                                                                |
| `version`     | String | HubSpot serverless function schema version. (Current version 1.0)                                                                                                                                                                                                                                            |
| `environment` | Object | Configuration variables passed to the executing function as [environment variables](https://nodejs.org/docs/latest-v10.x/api/process.html#process_process_env) 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 array containing the names of the [secrets](#secrets) your serverless function will use for authentication. Do not store secret values directly in this file, only reference secret names.                                                                                                                |
| `endpoints`   | Object | Endpoints define the paths that are exposed and their mapping to specific JavaScript files, within your functions folder. Learn more about [endpoints](#endpoints).                                                                                                                                          |

<Info>
  HubSpot will [no longer support Node 18](https://developers.hubspot.com/changelog/deprecation-of-node-v18-in-all-serverless-functions-and-cli) beyond October 1, 2025. Beyond that date, serverless functions with a runtime below v20 will not be able to be deployed.
</Info>

<Warning>
  **Please note:**

  Do not assign the same name to your secrets and environment variables. Doing so will result in conflicts when returning their values in the function.
</Warning>

### Endpoints

Each endpoint can have its own [environment variables](https://nodejs.org/docs/latest-v10.x/api/process.html#process_process_env) and secrets. Variables specified outside of endpoints should be used for configuration settings that apply to all functions and endpoints.

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

| key      | Type                       | Description                                                                                                                                                                                                           |
| -------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method` | String or array of strings | [HTTP method or methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods) that the endpoint supports. Defaults to [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/GET). |
| `file`   | String                     | Path to JavaScript function file with the implementation for the endpoint.                                                                                                                                            |

The endpoint can be invoked by calling a URL at one of the domains connected to HubSpot account, including the default `.hs-sites.com` subdomains, with the following URL structure:

`https://{domainName}/_hcms/api/{endpoint-name/path}?portalid={hubId}`.

| Parameter            | Description                                                                                                                                                               |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domainName`         | A domain connected to the HubSpot account.                                                                                                                                |
| `/_hcms/api/`        | The path reserved for serverless functions. All endpoints exist inside this path.                                                                                         |
| `endpoint-name/path` | The endpoint name or path that you specified in the `serverless.json` file.                                                                                               |
| `portalid`           | An optional query parameter containing your HubSpot account ID. Providing this in the request will enable you to test your functions within module and template previews. |

For example, if both `website.com` and `subdomain.brand.com` are connected to the account, you could call the function using either `https://website.com/_hcms/api/{endpoint-name/path}` or `https://subdomain.brand.com/_hcms/api/{endpoint-name/path}`.

## Function file

In addition to the `serverless.json` configuration file, the `.functions` folder will also contain a [Node.js](https://nodejs.org/en/) JavaScript file that defines the function. You can also leverage the [request](https://github.com/request/request#readme) library to make HTTP request to [HubSpot APIs](/api-reference/legacy/communication-preferences/v1/get-subscriptions-email) and other APIs.

For example:

```js theme={null}
// Require axios library, to make API requests.
const axios = require("axios");
// Environment variables from your serverless.json
// process.env.globalConfigKey

exports.main = (context, sendResponse) => {
  // your code called when the function is executed

  // context.params
  // context.body
  // context.accountId
  // context.limits

  // secrets created using the CLI are available in the environment variables.
  // process.env.secretName

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

### Context object

The context object contains contextual information about the function's execution, stored in the following parameters.

| Parameter   | Description                                                                                                                                                                                                                                                                                                                                                                                                              |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `accountId` | The HubSpot account ID containing the function.                                                                                                                                                                                                                                                                                                                                                                          |
| `body`      | 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 populated with a set of basic contact properties along with the following information:<ul><li>`vid`: The contact’s visitor ID.</li><li>`isLoggedIn`: when using CMS Memberships, this will be `true` if the contact is logged in to the domain.</li><li>`listMemberships`: an array of contact list IDs that this contact is a member of.</li></ul> |
| `headers`   | Contains the [headers](#headers) sent from the client hitting your endpoint.                                                                                                                                                                                                                                                                                                                                             |
| `params`    | Populated with query string values along with any HTML Form-POSTed values. These are structured as a map with strings as keys and an array of strings for each value.`context.params.yourvalue`                                                                                                                                                                                                                          |
| `limits`    | Returns how close you are to hitting the [serverless function rate limits](/cms/start-building/features/serverless-functions/overview#know-your-limits).<ul><li>`executionsRemaining`: how many executions per minute are remaining.</li><li>`timeRemaining`: how much allowed execution time is remaining.</li></ul>                                                                                                    |

### Headers

If you need to know the headers of the client that's hitting your endpoint, you can access them through `context.headers`, similar to how you would access information through `context.body`.

Below, review some of the common headers that HubSpot provides. For a full list, see [MDN's HTTP headers documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers).

| header                      | Description                                                                                                                                                                                                                                     |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accept`                    | Communicates which content types expressed as [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types), the client understands. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept). |
| `accept-encoding`           | Communicates the content encoding the client understands. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept-Encoding).                                                                                       |
| `accept-language`           | Communicates which human language and locale is preferred. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept-Language).                                                                                      |
| `cache-control`             | Holds directives for caching. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control).                                                                                                                     |
| `connection`                | Communicates whether the network connection stays open. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Connection).                                                                                              |
| `cookie`                    | Contains cookies by sent the client. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cookie).                                                                                                                     |
| `host`                      | Communicates the domain name and TCP port number of a listening server. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Host).                                                                                    |
| `true-client-ip`            | IP address of the end-user. [See Cloudflare true-client-ip](https://developers.cloudflare.com/network/true-client-ip-header/).                                                                                                                  |
| `upgrade-insecure-requests` | Communicates the clients preference for an encrypted and authenticated response. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Upgrade-Insecure-Requests).                                                      |
| `user-agent`                | Vendor defined string identifying the application, operating system, application vendor, and version. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent).                                                |
| `x-forwarded-for`           | Identifies the originating IP address of a client through a proxy or load balancer. [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For).                                                             |

#### 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.

```js theme={null}
sendResponse({
  statusCode: 301,
  headers: {
    Location: "https://www.example.com",
  },
});
```

### Set cookies from your endpoint

From your serverless function you can tell the client (web browser) to set a cookie.

```js theme={null}
exports.main = (context, sendResponse) => {
    sendResponse({
      body: { ... },
      'Set-Cookie': 'myCookie1=12345; expires=...; Max-Age=...',
      statusCode: 200
    });
  }
```

### Set multiple values for a single header

For headers that support multiple values, you can use `multiValueHeaders`, to pass the values. For example: you can tell the browser to set multiple cookies.

```js theme={null}
exports.main = (context, sendResponse) => {
  sendResponse({
    body: { ... },
    multiValueHeaders: {
      'Set-Cookie': [
        'myCookie1=12345; expires=...; Max-Age=...',
        'myCookie2=56789; expires=...; Max-Age=...'
       ]
    },
    statusCode: 200
  });
}
```

## Secrets

When you need to authenticate a serverless function request, you'll use secrets to store values such as API keys or private app access tokens. Using the CLI, you can add secrets to your HubSpot account to store those values, which you can later access through environment variables (`process.env.secretName`). Secrets are managed through the HubSpot CLI using the following commands:

* [`hs secrets list`](/developer-tooling/local-development/hubspot-cli/reference#list-secrets)
* [`hs secrets add`](/developer-tooling/local-development/hubspot-cli/reference#add-a-secret)
* [`hs secrets delete`](/developer-tooling/local-development/hubspot-cli/reference#remove-a-secret)

Once added through the CLI, secrets can be made available to functions by including a `secrets` array containing the name of the secret. This enables you to store your function code in [version control](/cms/start-building/introduction/developer-environment/github-integration) and use secrets without exposing them. However, you should <u>never</u> return your secret's value through console logging or as a response, as this will expose the secret in logs or in front-end pages that call your serverless function.

<Warning>
  **Please note:**

  Due to caching, it can take about one minute to see updated secret values. If you've just updated a secret but are still seeing the old value, check again after about a minute.
</Warning>

## 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)**](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/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.

<Info>
  **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 modify HubSpot's `Access-Control-Allow-Origin` header at this time.

  [See MDN for further detailed CORS error troubleshooting.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors)
</Info>

### Get requests

Get requests may be able to make [CORS requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) depending on the client. Do not make [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/GET) requests write anything, just return data.

## Preloaded packages

HubSpot serverless functions currently come preloaded with the following packages:

* [@hubspot/api-client](https://www.npmjs.com/package/@hubspot/api-client): ^1.0.0-beta
* [axios](https://www.npmjs.com/package/axios): ^0.19.2
* [request](https://www.npmjs.com/package/request): ^2.88.0
* [requests](https://www.npmjs.com/package/requests): ^0.2.2

To use the latest supported version of a preloaded package, or to use a newly added package:

1. Clone or copy your function file.
2. Change your function's endpoint in the `serverless.json` file to point to your new function file. You can safely delete the old version.

If you want to include packages outside of the preloaded package set, you can use [webpack](https://webpack.js.org/) to combine your node modules and have your bundled files be your function files.

## Limits

Serverless functions are intended to be fast and have a narrow focus. To enable quick calls and responses, HubSpot serverless functions have the following limits:

* 50 secrets per account.
* 128MB of memory.
* No more than 100 endpoints per HubSpot account.
* You must use `contentType` `application/json` when calling a function.
* Serverless function logs are stored for 90 days.
* 6MB on an AWS Lambda invocation payload.

**Execution limits**

* Each function has a maximum of 10 seconds of execution time.
* Each account is limited to 600 total execution seconds per minute.

This means either of these scenarios can happen:

* 60 function executions that take 10 seconds each to complete.
* 6,000 function executions that take 100 milliseconds to complete.

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](/developer-tooling/local-development/hubspot-cli/reference#get-logs).

To assist in avoiding these limits, limit data is provided automatically to the [function context](/cms/reference/serverless-functions/serverless-functions#function-file) during execution. You can use that to influence your application to stay within those limits. For example, if your application requires polling your endpoint, then you can return with your data a variable to influence the frequency of the polling. That way when traffic is high you can slow the rate of polling avoiding hitting limits, then ramp it back up when traffic is low.
