CRM data hooks
The CRM data hooks fetch data using the context of the CRM record where an extension is displayed. They handle loading state, error handling, and property formatting automatically. They also offer utility functions for data refetching and pagination. The CRM-specific hooks are only available in CRM extension points:crm.record.tab, crm.record.sidebar, crm.preview, and helpdesk.sidebar.
Learn more about using CRM data hooks on the hooks reference page.
fetchCrmObjectProperties action
Useactions.fetchCrmObjectProperties to fetch property values from the current CRM record imperatively. For example, when you need to control exactly when fetching occurs rather than fetching on render.
This action is only available in CRM extension points: crm.record.tab, crm.record.sidebar, crm.preview, and helpdesk.sidebar.
Learn more about using fetchCrmObjectProperties on the actions reference page.
Serverless functions
Usehubspot.serverless() to call a serverless function from your UI extension. Serverless JavaScript functions execute within HubSpot’s infrastructure, which eliminates the need to manage your own external server.
Learn more about serverless functions.
hubspot.fetch()
Usehubspot.fetch() to make requests from a UI extension to your own backend or a third-party API. It works in all extension points (app cards, app homes, app settings, etc.).
To fetch data using this method, you’ll need to:
- Provide a REST-based backend service to handle requests.
- Include the request URLs as
permittedUrlsin the app’s configuration.
Specify permitted URLs to fetch from
To make calls to your backend or a third-party service, update the app’s*-hsmeta.json configuration file to include the URLs you’ll be requesting. The URLs must be specified in the fetch array of permittedUrls.
- Fetch URLs must be valid HTTPS URLs and cannot be
localhost. If you want to send requests to a locally running backend, learn how to proxy requests. - Entries in
permittedUrls.fetchare treated as prefixes. A request tohttps://api.example.com/api/data/userswill be allowed ifhttps://api.example.com/api/data/is listed. - Wildcards are not supported.
- If a URL is not included in
permittedUrls.fetch, the request will fail with a 403 Forbidden error.
Method
The method contract forhubspot.fetch() is as follows:
Headers and metadata
To ensure that the requests hitting your backend are coming from HubSpot, several headers are included in the request. You can use these headers, along with the incoming request fields, to verify the signature of the request. Learn more about validating HubSpot requests. HubSpot will always populate headers related to request signing and also allow you to pass a customAuthorization header from hubspot.fetch(). See the example hubspot.fetch() request with Authorization header for more information. All other client-supplied request headers are stripped. Response headers from your backend are not returned. HubSpot can add its own response headers, including X-HubSpot-Fetch-Error-Source: proxy to identify proxy error responses.
HubSpot also automatically adds the following query parameters to each request to supply metadata:
userIdportalIduserEmailappId
Limits
Requests made withhubspot.fetch() are subject to the following limits:
- Concurrency: each app is allowed up to 20 concurrent requests per account, shared across users and extensions in that account. Additional requests receive
429responses and can be retried after a delay. See Handle error responses to distinguish a HubSpot concurrency-limit response from your backend’s429response. - Timeout: each request has a default timeout of 15 seconds. It can be increased up to 120 seconds (2 minutes) using the
timeoutoption. HubSpot will automatically retry a request once if there are issues establishing a connection, or if the request fails with a5XXstatus code within the timeout window. Request duration time includes the time required to establish an HTTP connection. - Payload size: both request and response payloads are limited to 1 MB.
hubspot.fetch() is not a one-to-one replacement. Key differences between the two APIs are listed below.
Handle error responses
A429 response resolves the hubspot.fetch() promise with a Response whose status is 429 and ok is false. Existing status-based error handling continues to work. Timeouts, invalid requests, and transport failures can reject the promise instead.
To identify a HubSpot proxy concurrency-limit response, check for both status 429 and the X-HubSpot-Fetch-Error-Source: proxy response header. HubSpot sets this header in the extension runtime; it is not forwarded from your backend. A backend response with the same error message or category does not receive this header.
Marked proxy error responses include a JSON body with status, category, message, and an optional correlationId. For example, a concurrency-limit response has this shape:
429 responses retain their original body and do not receive the source header. The following example inspects marked proxy responses and handles other 429 responses separately:
Concurrency-limit
429 responses do not include a Retry-After hint, and HubSpot does not automatically retry these requests. Add a delay before retrying, and bound the number of retries. A retry is not guaranteed to succeed after a fixed interval. The concurrency limit remains 20 requests per app per account.Proxying requests to a locally running backend
If you have a locally running backend, you can set up a proxy to remaphubspot.fetch() requests made during local development. This proxy is configured through a local.json file in your project, and will prevent requests from being routed through HubSpot’s data fetch service.
To proxy requests to a locally running backend:
- Create a
local.jsonfile in the same directory as yourpublic-app.jsonfile. In this file, define a proxy that remaps requests made usinghubspot.fetch(). This mapping will only happen for the locally running extension. You can include multiple proxy key-value pairs in theproxyobject.
- Upload your project by running
hs project upload. - With your project uploaded, run
hs project devto start the development server. The CLI should confirm that it has detected your proxy.
- When you request the mapped URL using
hubspot.fetch(), the CLI will confirm the remapping.
Request signatures during proxied local development
By default, when proxying requests during local development, requests will not be signed or include metadata in query parameters. However, if you want to introduce request signing into the local development process, you can inject theCLIENT_SECRET environment variable into the local development process.
Injecting CLIENT_SECRET
After setting up yourlocal.json file to proxy specific domains, you can inject the CLIENT_SECRET variable when starting the local development server by prepending the hs project dev command with the variable:
CLIENT_SECRET value, as long as you inject the same variable in your locally running backend that you’re using for hs project dev. For example, your backend might include the following Node or Python code:
CLIENT_SECRET variable:
CLIENT_SECRET variable from your app into the hs project dev command permanently. For ease of use, consider baking the variable into your start scripts for local development.
To validate HubSpot request signatures in your custom backend, check out the request validation guide. You can also use HubSpot’s @hubspot/api-client npm module to verify requests and sign them yourself. For example:
hubspot.fetch examples
Below are examples ofhubspot.fetch requests to illustrate basic and authorization header usage.
Basic usage
Authorization header
You may return a short-lived authorization token from your backend service after validating the HubSpot signature. You can then use this token to access other resources. To get the access token from your backend server in the UI extension:Monitoring and logs
To monitorhubspot.fetch() activity, you can view request logs in HubSpot:
- In your HubSpot account, navigate to Development.
- In the left sidebar, navigate to Monitoring > Logs.
- On the monitoring page, click the UI Extensions tab.
