Power Plus - Datasource: JSON
Loads data from any JSON API or hosted JSON file. The most versatile datasource — supports REST APIs, public datasets, and static files. Optional JSONata transformations let you reshape data into the format the list needs. All processing happens client-side in the browser.
The JSON Datasource module loads data from any JSON API endpoint or hosted JSON file. It’s the most versatile datasource in the framework — you can connect to REST APIs, public datasets, third-party services, or static files hosted in HubSpot’s file manager. If an API returns JSON, this datasource can work with it.
The JSON datasource is a client-side datasource, meaning the data is fetched once into the browser and all filtering, sorting, searching, and paging are performed locally in JavaScript. This makes interactions feel instant (no network delay after the initial load) but means the full dataset must fit comfortably in the browser’s memory. For most use cases (up to a few thousand items), this works perfectly.
Configuration
|
Field |
Type |
Description |
|---|---|---|
|
Name |
Text |
A unique identifier for this datasource (e.g. |
|
URL |
URL |
The JSON endpoint to fetch. Can be an external URL (e.g. |
|
JSON Query |
Text |
A JSONata expression applied to the raw API response to extract the array of items. This is where the real power lies — you can navigate nested structures, transform data shapes, merge fields, filter at the source, and compute derived values. |
Advanced Options
|
Field |
Description |
|---|---|
|
Search Fields |
A JSONata expression returning an array of field values to search through. Example: |
|
Test Data |
Paste raw JSON here to test your configuration without hitting the actual API. When test data is provided, the datasource uses this JSON instead of fetching from the URL. This is useful during development: you can fine-tune your JSON Query and renderer configuration without waiting for API responses or worrying about rate limits. Remove the test data before going live. |
How It Works
-
When the page loads, the datasource fetches the JSON from the URL using a browser
fetch()request. -
The JSON Query is applied to the raw response using JSONata to extract and optionally transform the items array.
-
The framework builds a schema from the extracted data by scanning every item and collecting all field names, types, and unique values. This schema powers data-schema filters and the debug console output.
-
The resulting array is stored in memory and used as the data pool for all subsequent filtering, sorting, searching, and paging — no additional network requests are made.
When a visitor interacts with a filter, sort, or search control: - The framework applies the filter conditions to the in-memory data - Search narrows the results further - Sort reorders the remaining items - Paging splits them into chunks for rendering
All of this happens instantly in the browser because the data is already loaded.
Examples
Simple REST API
Load items from a REST API that returns a standard results array:
Name: my_datasource
URL: https://api.example.com/items
JSON Query: results
If the API returns:
{
"total": 42,
"results": [
{ "id": 1, "name": "Item A", "price": 29.99, "category": "electronics" },
{ "id": 2, "name": "Item B", "price": 49.99, "category": "clothing" }
]
}
The results JSONata query extracts just the array of items, discarding the total wrapper. Each item becomes a data object available to renderers and filters.
Greenhouse Job Board (with Data Transformation)
The Greenhouse API returns job metadata in a nested metadata array. To make department and employment type filterable, the JSON Query extracts them into flat properties:
Name: jobs_datasource
URL: https://boards-api.greenhouse.io/v1/boards/yourcompany/jobs
JSON Query: $map(jobs, function($v) {
$merge([$v, {
'employment_type': $v.metadata[name.$contains('Employment')].value,
'department': $v.metadata[name.$contains('Department')].value
}])
})
Step by step:
1. $map(jobs, function($v) { ...
}) — iterates over every job in the jobs array.
2. $v.metadata[name.$contains('Employment')].value — finds the metadata entry whose name contains “Employment” and extracts its value.
3. $merge([$v, { 'employment_type': ...,
'department': ... }]) — creates a new object that has all the original job fields plus the extracted employment_type and department as flat top-level properties.
The result is that you can now create simple data-schema filters for employment_type and department without needing to navigate the nested metadata structure in every filter configuration.
HubDB via Public API
While there is a dedicated HubDB Datasource module, you can also use the JSON datasource with the HubDB API directly. This is useful when you need JSONata transformations on the raw HubDB data before it enters the list:
Name: content_library_ds
URL: https://api.hubapi.com/cms/v3/hubdb/tables/YOUR_TABLE_ID/rows?portalId=YOUR_PORTAL_ID
JSON Query: results
Search Fields: [values.name]
Replace YOUR_TABLE_ID and YOUR_PORTAL_ID with your actual values. The HubDB API returns {
results: [...] } so the query is simply results.
Weather Data for Charts
Fetch weather data from the Open-Meteo API and reshape its parallel arrays into per-hour objects for the Chart renderer:
Name: chart_datasource
URL: https://api.open-meteo.com/v1/forecast?latitude=48.15&longitude=11.38&past_days=10&hourly=temperature_2m,relativehumidity_2m,windspeed_10m
JSON Query: $map($.hourly.time, function($v, $i) {
{
"id": $i,
"time": $v,
"temp": $.hourly.temperature_2m[$i],
"wind": $.hourly.windspeed_10m[$i],
"millis": $toMillis($v & ":00"),
"humidity": $.hourly.relativehumidity_2m[$i]
}
})
The Open-Meteo API returns data as parallel arrays (one array for times, one for temperatures, one for wind speeds, etc.). This JSONata query zips them together into an array of objects — each object represents one hour with all its measurements. The $toMillis($v
& ":00") converts the ISO timestamp to epoch milliseconds, which the Chart renderer needs for time-based axes and which the time-based manual filter can compare against.
Static File from HubSpot File Manager
Point the URL to a JSON file hosted in HubSpot’s file manager. This is useful for small, manually maintained datasets (team members, office locations, FAQ items):
Name: team_datasource
URL: (select a file from the File Manager picker)
JSON Query: members
The file picker in HubSpot’s editor lets you browse the file manager and select a JSON file. The file’s URL is automatically inserted.
JSONata in the JSON Query
The JSON Query field accepts full JSONata expressions. This is the single most powerful feature of the JSON datasource because you can reshape any API response into the exact format you need. Common patterns:
-
Navigate nested data:
response.data.items— drills into nested objects to find the array. -
Filter at the source:
items[status = 'active']— removes items you never want to show before they even enter the list. -
Transform/reshape:
$map(items, function($v) { ... })— restructure each item. -
Merge fields:
$merge([$v, {'extra': $v.nested.value}])— add derived fields from nested data. -
Sort at the source:
items^(name)— pre-sort ascending by name.items^(>date)— pre-sort descending by date. -
Compute values:
$merge([$v, {'total': $v.price * $v.qty}])— add calculated fields. -
String manipulation:
$merge([$v, {'slug': $lowercase($replace($v.name, ' ', '-'))}])— derive URL slugs. -
Flatten arrays:
$reduce(categories, function($prev, $next) { $append($prev, $next.items) }, [])— combine items from multiple categories into one flat list.
The JSON Query runs once when data is loaded. Its output becomes the dataset for everything else — filters, sort, search, and rendering all work on the query’s output.
See the JSONata documentation for the full expression reference and more examples.