Last modified: August 22, 2025
Please note:This page contains reference documentation for newer, project-based serverless functions. For serverless functions built using the design manager, check out the serverless functions (design manager) reference. If you’re looking to implement serverless functions in a UI extension, check out the CRM customization guide.
serverless.json
configuration, enable the use of third-party dependencies, and have more direct access to private app access tokens for authentication.
For a high-level overview of serverless functions, see the serverless functions overview. And to get started building project-based serverless functions, check out the get started guide.
File structure
Serverless functions are packaged within a.functions
directory within the app
directory of a project. The .functions
directory can have any name you’d like, as long as it ends in .functions
.
In the .functions
directory, you’ll need to include three files:
serverless.json
: the configuration file for the serverless function.function.js
: A JavaScript file containing the code to execute. This file can have any name, and you’ll reference the file name inserverless.json
.- A
package.json
configuration file to contain the dependencies needed to execute the function.
Serverless.json
Theserverless.json
file stores the serverless function configuration. This is a required file, and maps your functions to their endpoints.
Please note:If you’re upgrading your existing serverless functions to be built using developer projects, note that the
runtime
, environment,
and version
fields have been removed.Field | Type | Description |
---|---|---|
functionName | Object | An object containing the serverless function’s configuration details. This object can have any name. |
file | String | The name of the JavaScript file containing the serverless function code to execute. |
secrets | Array | An array containing names of secrets that the function will use for authenticating requests. Learn more about authentication. |
endpoint | Object | An object containing details about the endpoint that you can hit to invoke the function. The path field defines the last value in the /hs/serverless/<path> endpoint path, while the method field defines the request method. Learn more about endpoints. |
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.
Function file
Serverless functions built with developer projects use the NodeJS runtime (version 18 and higher). Lower versions of Node cannot be specified. In addition, serverless functions should be asynchronous, usingawait
and try
/catch
instead of promise chaining.
Below is an example of JavaScript code that can be executed by a serverless function. This code is taken from the get started with serverless functions guide and fetches a quote via the Zen Quotes API. Learn more about authenticating requests.
package.json
In thepackage.json
file, you can specify dependencies to include in the dependencies
field. 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:
Endpoints
Serverless functions for the CMS are invoked by calling its public URL, which has the following structure:https://<domain>/hs/serverless/<path>
.
Parameter | Description |
---|---|
<domain> | A domain connected to the HubSpot account. This can be any connected domain, including the default <hubId>.hs-sites.com domain. |
/hs/serverless/ | The path reserved for serverless functions. All endpoints exist inside this path. |
<path> | The path value specified in the serverless.json file. |
https://website.com/hs/serverless/<path>
or https://subdomain.brand.com/hs/serverless/<path>
. If the serverless function’s path
field was set to fetch-quote
, the full URL would be:
https://website.com/hs/serverless/fetch-quote
Authentication
Serverless functions requests built with projects can be authenticated using either the app’s private app access token or a secret. Calls authenticated with private app access tokens count against your API call limits.- Private app access tokens can be used for authenticating HubSpot API requests, using the value
PRIVATE_APP_ACCESS_TOKEN
. - Secrets can be referenced by name, and must also be included in the
secrets
array of theserverless.json
file. To create, manage, and view secrets associated with your account, use the set ofhs secrets
CLI commands. - In the function file, authentication for app tokens and secrets are both accessed with
process.env
.
headers
object).
- Private app access token
- Secret auth
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 method is 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:
|
headers | Contains the 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. |
Headers
If you need to know the headers of the client that’s hitting your endpoint, you can access them throughcontext.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.
header | Description |
---|---|
accept | Communicates which content types the client understands, expressed as MIME types. 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 sent by 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 and301
statusCode.
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
ofapplication/json
when calling a function. - Serverless function logs are stored for 90 days.
- 6MB on an AWS Lambda invocation payload.
- Each function has a maximum of 10 seconds of execution time.
- Each account is limited to 600 total execution seconds per minute.
- 60 function executions that take 10 seconds each to complete.
- 6,000 function executions that take 100 milliseconds to complete.
429
response. The execution time of each function is included in the serverless function logs.
To assist in avoiding these limits, limit data is provided automatically to the function context 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.