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
    }
  ]
}