Custom Data
Custom Data are stored in Tables defined by a set of Fields where each Field has properties to define type and constraints.
Tables
When creating a Table, you specify the full structure with Fields and all.
Create a new Table
POST https://<host>/v1/hubs/32323/customdata/tables HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"name": "East_Region", (1)
"languageIds": [9, 20],
"defaultLanguageId": 9,
"dataSetName": "clients", (2)
"fields":[
{"name": "Name", "dataType": "Text", "isPrimaryKey": "true", "length": 255}, (3)
{"name": "City", "dataType": "Text"},
{"name": "Contact", "dataType": "Text"}
]
}
1 | The table-name needs to be unique. |
2 | Tables are organized in DataSets. If a DataSet with the provided name does not exist, it will be automatically created. |
3 | Note! A Table needs at least one field with the isPrimaryKey property set to true. |
Response
{
"id": 234,
"hubId": 32323,
"name": "East_Region",
"dataSetId": "s23",
"dataSetPublicName": "clients",
"created": "2025-02-04T08:43:23.2+00:00",
"createdByUserId": 33,
"lastModified": "2025-02-04T08:43:23.36+00:00"
}
Get a specific Table
GET https://<host>/v1/hubs/32323/customdata/tables/23 HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
{
"id": 234,
"hubId": 32323,
"name": "East_Region",
"dataSetId": "s23",
"dataSetPublicName": "clients",
"created": "2025-02-04T08:43:23.2+00:00",
"createdByUserId": 33,
"lastModified": "2025-02-04T08:43:23.36+00:00"
}
Get tables in a Hub
GET https://<host>/v1/hubs/32323/customdata/tables?$top=2&$skip=0&$orderBy=Name&$filter=region HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
{
"itemType": "CustomTable",
"itemCount": 2,
"totalCount": 2,
"items": [
{
"id": 234,
"hubId": 32323,
"name": "East_Region",
"dataSetId": "s23",
"dataSetPublicName": "clients",
"created": "2025-02-04T08:43:23.2+00:00",
"createdByUserId": 33,
"lastModified": "2025-02-04T08:43:23.36+00:00"
},
{
"id": 237,
"hubId": 32323,
"name": "West_Region",
"dataSetId": "s27",
"dataSetPublicName": "clients",
"created": "2025-02-04T08:45:23.2+00:00",
"createdByUserId": 33,
"lastModified": "2025-02-04T08:43:23.36+00:00"
},
]
}
Delete a Table
DELETE https://<host>/v1/hubs/32323/customdata/tables/234 HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Fields
Get all Fields in a Table
GET https://<host>/v1/hubs/32323/customdata/tables/234/fields HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
{
"itemType": "CustomTableField",
"itemCount": 3,
"totalCount": 3,
"items": [
{
"id": 37,
"name": "Name",
"isPrimaryKey": true,
"dataType": "text",
"length": 255,
"isLanguageDependent": false,
"categories": []
},
{
"id": 38,
"name": "City",
"isPrimaryKey": false,
"dataType": "text",
"isLanguageDependent": false,
"categories": []
},
{
"id": 39,
"name": "Contact",
"isPrimaryKey": false,
"dataType": "text",
"isLanguageDependent": false,
"categories": []
}
]
}
Add a new numerical Field to a Table
POST https://<host>/v1/hubs/32323/customdata/tables/234/fields HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"name": "Population",
"dataType": "Numeric",
"precision": 10,
"scale": 0
}
Response
{
"id": 40,
"name": "Population",
"isPrimaryKey": false,
"dataType": "numeric",
"precision": 10,
"scale": 0,
"isLanguageDependent": false,
"categories": []
}
Add a new categorical Field to a Table
POST https://<host>/v1/hubs/32323/customdata/tables/234/fields HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"name": "Cat",
"dataType": "categorical",
"length": 3,
"categories": [
{
"code": "one",
"labels": [
{
"label": "ONE",
"language": 9
},
{
"label": "EN",
"language": 20
}
]
},
{
"code": "two",
"labels": [
{
"label": "TWO",
"language": 9
},
{
"label": "TO",
"language": 20
}
]
}
]
}
Response
{
"id": 41,
"name": "Cat",
"isPrimaryKey": false,
"dataType": "categorical",
"length": 3,
"isLanguageDependent": false,
"categories": []
}
Delete a Field
DELETE https://<host>/v1/hubs/32323/customdata/tables/234/fields/40 HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Categories
Categories are not included in the Fields - endpoint, so you need to use the specific Categories - endpoint.
Get all Categories for a Field
GET https://<host>/v1/hubs/32323/customdata/tables/234/fields/41/categories HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
{
"itemType": "CustomTableFieldCategory",
"itemCount": 2,
"totalCount": 2,
"items": [
{
"labels": [
{
"language": 9,
"label": "ONE"
},
{
"language": 20,
"label": "EN"
}
],
"code": "one"
},
{
"labels": [
{
"language": 9,
"label": "TWO"
},
{
"language": 20,
"label": "TO"
}
],
"code": "two"
}
]
}
Add new Categories to a Field
POST https://<host>/v1/hubs/32323/customdata/tables/234/fields/41/categories HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
[
{
"labels": [
{
"language": 9,
"label": "THREE"
},
{
"language": 20,
"label": "TRE"
}
],
"code": "tre"
}
]
Replace Categories for a Field
PUT https://<host>/v1/hubs/32323/customdata/tables/234/fields/41/categories HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
[
{
"labels": [
{
"language": 9,
"label": "ONEEE"
},
{
"language": 20,
"label": "ENNN"
}
],
"code": "one"
},
{
"labels": [
{
"language": 9,
"label": "TWOOO"
},
{
"language": 20,
"label": "TOOO"
}
],
"code": "two"
},
{
"labels": [
{
"language": 9,
"label": "THREEEE"
},
{
"language": 20,
"label": "TREEE"
}
],
"code": "tre"
}
]
Records
Add new Records to a Table
POST https://<host>/v1/hubs/32323/customdata/tables/234/records HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"dataSchema":
{
"fieldNames": ["Name", "City"] (1)
},
"data":[
{"Name": "n1", "City": "NY"}, (2)
{"Name": "n2", "City": "LA"}
]
}
1 | Not all fields needs to be added, but the Primary key(s) needs to be included. |
2 | Each record should at least have the key-field specified. |
Response
{
"insertedRecords": 2,
"updatedRecords": 0
}
Get Records in a Table
GET https://<host>/v1/hubs/32323/customdata/tables/234/records?$top=20&$skip=0&$orderBy=Name&$filter= HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
{
"itemType": "CustomTableRecord",
"itemCount": 2,
"totalCount": 2,
"items": [
{
"__recordId": 1, (1)
"isDeleted": false,
"Name": "n1",
"City": "NY",
"Contact": null, (2)
"Population": null,
"Cat": null
},
{
"__recordId": 2,
"isDeleted": false,
"Name": "n2",
"City": "LA",
"Contact": null,
"Population": null,
"Cat": null
}
]
}
1 | Each record will be assigned a unique id by the system |
2 | Fields not populated will appear as null-values. |
Update existing Records in a Table
PUT https://<host>/v1/hubs/32323/customdata/tables/234/records HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"dataSchema":
{
"fieldNames": ["Name", "City", "Contact"] (1)
},
"data":[
{"Name": "n1", "City": "NY", "Contact": "c1"},
{"Name": "n3", "City": "LA", "Contact": "c2"} (2)
]
}
1 | Note that a new Field will be added . |
2 | This record will not be updated as there is no existing record with the matching key "n3". |
Response
{
"insertedRecords": 0,
"updatedRecords": 1
}
Merge Records in a Table
PATCH https://<host>/v1/hubs/32323/customdata/tables/234/records HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"dataSchema":
{
"fieldNames": ["Name", "City", "Contact"]
},
"data":[
{"Name": "n1", "City": "NY", "Contact": "c11"},(1)
{"Name": "n3", "City": "LA", "Contact": "c22"} (2)
]
}
1 | This record will be updated as the key already exists. |
2 | This record will added. |
Response
{
"insertedRecords": 1,
"updatedRecords": 1
}
Delete a set of Records from a Table
DELETE https://<host>/v1/hubs/32323/customdata/tables/234/records HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"dataSchema":
{
"keys": ["Name"]
},
"data":[
{"Name": "n1"},
{"Name": "n3"},
{"Name": "n4"}(1)
]
}
1 | Records with non-exising keys will be ignored. |
Get a specific Record in a Table
GET https://<host>/v1/hubs/32323/customdata/tables/234/records/2 HTTP/1.1 (1)
Accept: application/json
Authorization: Bearer <access_token>
1 | Note the usage of the unique __recordId property. |
Response
{
"__recordId": 2,
"isDeleted": false,
"Name": "n2",
"City": "LA",
"Contact": null,
"Population": null,
"Cat": null
}
Update a specific Record in a Table
PUT https://<host>/v1/hubs/32323/customdata/tables/234/records/2 HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer <access_token>
{
"Population": 4566,
"Cat": "tre"
}
Delete a specific Record in a Table
DELETE https://<host>/v1/hubs/32323/customdata/tables/234/records/2 HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Changes
The datastate - and changed-records - endpoints can be used to only fetch records that has changed since "last" time.
If current datastate is 5, then calling changed-records with stateId 4 will return those records that have changed after 4.
Get current DataState for a Table
GET https://<host>/v1/hubs/32323/customdata/tables/234/datastate HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Response
5
Get changed Records for a Table
GET https://<host>/v1/hubs/32323/customdata/tables/234/changed-records?stateId=4&includeDeletes=true HTTP/1.1 (1)
Accept: application/json
Authorization: Bearer <access_token>
1 | If stateId is blank, all records will be returned. Use includeDeletes to include deleted records (isDeleted=true). |
Response
{
"itemType": "CustomTableRecord",
"itemCount": 2,
"totalCount": 2,
"items": [
{
"__recordId": 1,
"isDeleted": false,
"Name": "n1",
"City": "NY",
"Contact": "c3",
"Population": null,
"Cat": null
},
{
"__recordId": 2,
"isDeleted": false,
"Name": "n2",
"City": "LA",
"Contact": null,
"Population": 56,
"Cat": null
}
]
}