HubDB
This API is in beta.
This API is currently under development. For the latest stable version check out this page
HubDB is a relational data store representing data as rows, columns, and cells in a table, much like a spreadsheet.
Data in a HubDB table can be accessed from HubSpot pages using HubL or the JSON REST APIs. Endpoints that support GET
also support CORS
, so you can access the data in a table client-side using JavaScript and an account ID (often called Hub ID). Note: This only applies to GET methods. Other methods and the GET
all tables API require authentication, and will not support CORS.
Modifying HubDB tables
HubDB tables can be modified in HubSpot, making it easy for anyone to add or modify data in those tables. You can also use the API for this.
For more details and information on using data in a HubDB table on a HubSpot site, click here.
Rate limits
HubDB API requests have different rate limits, depending on the type of request:
- Any
GET
requests made that don't require authentication (including client-side JavaScript requests) are limited to 10 requests per second. These requests will not count towards the daily limit. - All other requests using authentication follow the standard limits.
Changes in V3:
- Tables should have both name and label. This name cannot be changed once the table is created. Names can only include lowercase letters, digits, and underscores and cannot begin with a number. Both name and label should be unique in the account.
- API supports both table id and name in the URL paths.
GET
row endpoints return column name instead of id in values field. Also,POST
/PUT
/PATCH
row endpoints require column name instead of id in values field.- Row update
PATCH
endpoints now accept sparse updates, which means we can specify only the column values that we need to update (whereas we had to specify all the column values in the previous versions). When you update a column with a list of values such as multi-select, you need to specify the list of all the values. In order to delete the value for a column, you need to specify the column with the value as null in the request. - Removed the endpoints to
get
/update
/delete
a row cell in favor of the row updatePATCH
endpoints. - Import endpoint now supports an optional field idSourceColumn along with existing fields in the JSON-formatted options. You can use this field to specify the column in the csv file which contains row ids. To import new rows along with the new values for existing rows, you can simply specify 0 as the row id for the new rows and the valid row ids for the existing columns. See more details in the Import section below. Also you can use column names or ids in the target field of the column mappings in the JSON-formatted options.
- Clone endpoint requires a new name and new label.
Draft vs Live Versions
HubDB tables have both draft and live versions and live versions can be published or unpublished. This will allow you to update data in the table, either for page previews or testing or to allow for a manual approval process, without affecting any live pages. Draft data can be reviewed and then pushed live / published by a user working in HubSpot, or via /push-live
endpoint of the API. The draft data can also be discarded via /reset
endpoint, allowing users to go back to the current live version of the data without disruption.
Creating tables
Tables can have the following fields:
Required fields |
How to use |
Description |
Name |
|
The internal name of the table. This name cannot be changed once the table is created. Names can only include lowercase letters, digits, and underscores and cannot begin with a number. |
Label |
|
Label of the table. This is what users will see when editing the table in HubSpot. |
Optional fields |
How to use |
Description |
Use for dynamic pages |
|
Set this to true to use the page for dynamic pages. |
Columns |
|
A list of column definitions that will be used for the table. |
Allow public API access |
|
Set this to true to allow public API access without any auth. |
Allow child tables |
|
Set this to true to allow child tables for each row. |
Enable dynamic pages for child tables |
|
Set this to true to create dynamic pages for child tables |
Column
Each column should include the following fields:
Field |
How to use |
Description |
Name |
|
The internal name of the column. This name cannot be changed once the column is created |
Label |
|
Optional - The label for the column. This is what users will see when editing the table in HubSpot. |
Type |
|
The data type of the column. Must be one of
|
Options |
|
If the column is the |
Example request for table creation
//example request
{
"label": "Test Table",
"name": "test_table",
"columns": [
{
"name": "text_column",
"label": "Text Column",
"archived": false,
"type": "TEXT"
},
{
"name": "number_column",
"label": "Number Column",
"archived": false,
"type": "NUMBER"
},
{
"name": "multiselect",
"label": "Multi Select Column",
"archived": false,
"options": [
{
"id": "1",
"name": "Option 1",
"type": "option"
},
{
"id": "2",
"name": "Option 2",
"type": "option"
}
],
"type": "MULTISELECT"
}
],
"useForPages": true,
"allowChildTables": true,
"enableChildTablePages": false,
"dynamicMetaTags": {
},
"allowPublicApiAccess": false
}
While updating existing tables or columns, include the "id " field as well.
Creating table rows
Rows should include the following fields:
Optional fields |
How to use |
Description |
Path |
|
If the table is enabled for dynamic pages, this is the path suffix used for the page for this row. |
Page title |
|
If the table is enabled for dynamic pages, this is the HTML title used for the page for this row. |
Child table id |
|
Specify the child table id for multi-level dynamic pages. |
Values |
|
A list of values for the cells in the row. Each entry requires a column name you’d get when pulling the table details and the value being set for that column. For example, when setting a column test and type |
While updating existing rows, include "id " field in the input object.
Example request for table creation
//example request
{
"values": {
"text_column": "sample text value",
"number_column": 76,
"rich_text_column": "<strong>This is a styled paragraph.</strong>",
"date_column": 1591228800000,
"date_time_column": 1604450520000,
"boolean_column": 1,
"select_column": {
"id": "1",
"name": "option 1",
"type": "option"
},
"multiselect_column": [
{
"id": "1",
"name": "Option 1",
"type": "option"
},
{
"id": "2",
"name": "Option 2",
"type": "option"
}
],
"url_column": "https://www.hubspot.com/marketing",
"video_column": 3392210008,
"image_column": {
"url": "https://f.hubspotusercontentqa00.net/hubfs/99992002/image3%20(1).jpg",
"width": 1600,
"height": 900,
"type": "image"
},
"foreign_id_column": [
{
"id": "4364402239",
"type": "foreignid"
},
{
"id": "4364402240",
"type": "foreignid"
}
]
},
"path": "test_path",
"name": "test_title",
"childTableId": "1902373"
}
Importing tables
Import endpoint takes a multi-part POST
request. The first part will be a set of JSON-formatted options for the import and you can specify this with the name as " config ". The second part will be the CSV file you want to import and you can specify this with the name as " file ".
Include the following fields as a JSON string in the JSON-formatted options.
Field name |
How to use |
Description |
skipRows |
|
The number of header rows that should be skipped over. Defaults to |
separator |
|
Column delimiter in the CSV file. Default is |
idSourceColumn* |
|
The index of the column in the source file containing the row’s |
resetTable |
|
Defaults to |
nameSourceColumn |
|
The index of the column in the source file containing the row’s |
pathSourceColumn |
|
The index of the column in the source file containing the row’s |
childTableSourceColumn |
|
The index of the column in the source file containing the row’s |
columnMappings |
|
A list of mappings for the columns in the source file to the columns in the destination HubDB table. Each mapping must have the following format: |
primaryKeyColumn |
|
The name of a column in the target HubDB table to use for row deduplication. |
encoding |
|
Encoding type. (utf-8, ascii, iso-8859-2, iso-8859-5, iso-2022-jp, windows-1252) |
format |
|
Unused. Only CSV is supported. |
We have two options while importing the data into the table: Add Rows
and Reset
.
- With reset table option (can be specified as
"resetTable":true
in the JSON-formatted options)- if the rows in the csv file does not have a row id column or row id is specified as
0
, those rows will be inserted with the new row ids generated. - if the row ids in the csv file already exists in the target table, the existing rows in the table will be updated with the new values from the input file.
- if the table has rows but the input csv file does not have those row ids, those rows will be deleted from the target table.
- if the row ids in the input csv file do not exist in the target table, those rows will be inserted with the new row ids generated and the row ids given in the input file will be ignored.
- if the input csv file does not contain the row id column at all, all the rows will be deleted from the target table and the rows from the input file will be inserted with the new row ids generated.
- if the rows in the csv file does not have a row id column or row id is specified as
- With add rows option (can be specified as "
resetTable":false
in the JSON-formatted options)- if the row ids in the csv file already exists in the target table, the existing rows in the table will be updated with the new values from the input file.
- if the table has rows but the input csv file does not have those row ids, those rows will not be deleted from the target table and those rows will remain unchanged.
- if the row ids in the input csv file do not exist in the target table, those rows will be inserted with the new row ids generated and the row ids given in the input file will be ignored.
- if the rows in the csv file does not have a row id column or row id is specified as 0, those rows will be inserted with the new row ids generated.
Example JSON config
//example config
{
"skipRows":1,
"format":"csv",
"separator":",",
"encoding":"utf-8",
"columnMappings": [
{"target":1,"source":"text_column"},
{"target":2,"source":"number_column"},
{"target":3,"source":"multiselect"}
],
"idSourceColumn":1,
"pathSourceColumn":2,
"nameSourceColumn":4,
"childTableSourceColumn":5,
"resetTable":true
}
Example curl command for the import endpoint:
//example curl command
curl 'https://api.hubapi.com/cms/v3/hubdb/tables/lesson/draft/import?portalId=99992002&hapikey=apikey'
-H 'accept: application/json, text/javascript, */*; q=0.01'
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundaryelAAdi3MTqAK2hrt' -H 'sec-fetch-site: same-origin'
-H 'sec-fetch-mode: cors'
-H 'sec-fetch-dest: empty'
--data-binary
$'------WebKitFormBoundaryelAAdi3MTqAK2hrt\r\nContent-Disposition:
form-data; name="config"\r\n\r\n{"skipRows":1,"format":"csv","separator":",","encoding":"iso-8859-1","columnMappings":[{"target":"name","source":6},{"target":"lesson_order","source":7},{"target":"rich_text","source":8}],"idSourceColumn":1,"pathSourceColumn":null,"nameSourceColumn":null,"childTableSourceColumn":null,"resetTable":true}\r\n------WebKitFormBoundaryelAAdi3MTqAK2hrt\r\nContent-Disposition: form-data; name="file"; filename="sample_input_file.csv"\r\nContent-Type: text/csv\r\n\r\n\r\n------WebKitFormBoundaryelAAdi3MTqAK2hrt--\r\n'
--compressed;