Data sources
Creating a data source (Custom List)
A class that inherits from Peakboard.ExtensionKit.CustomListBase represents a single data source – internally called a Custom List. It defines the configurable inputs, the output columns and the row-retrieval logic.
Important
Every class that inherits from CustomListBase must be marked with the [Serializable] attribute. This is required for proper serialization and compatibility within Peakboard.
using Peakboard.ExtensionKit;
namespace HubSpot;
[Serializable]
internal class HubSpotCustomList : CustomListBase
{
// overrides (see below)
}
Metadata and user input: GetDefinitionOverride
GetDefinitionOverride returns a CustomListDefinition with the metadata of the data source. The PropertyInputDefaults collection represents the settings the end user configures in the Peakboard Designer:
protected override CustomListDefinition GetDefinitionOverride()
{
return new CustomListDefinition
{
ID = "CatFactsCustomList",
Name = "Cat Facts",
Description = "Random cute stuff about cats",
PropertyInputPossible = true,
PropertyInputDefaults =
{
new CustomListPropertyDefinition() { Name = "MaxLength", Value = "140" },
new CustomListPropertyDefinition() { Name = "Token", Value = "Enter your API token here", Masked = true }
}
};
}
The properties defined here appear as input fields in the Designer:

A property (CustomListPropertyDefinition) can have the following attributes:
| Attribute | Description |
|---|---|
Name |
The name of the property. |
Value |
The default value. |
MultiLine |
Gives the user a large text field (e.g. for SQL statements). |
Masked |
Hides the value from the user (e.g. for passwords or API tokens). |
The values entered by the user are read in GetColumnsOverride and GetItemsOverride via the data.Properties dictionary:
string token = data.Properties["Token"];
Output columns: GetColumnsOverride
GetColumnsOverride is called when the Designer needs the schema (columns) of the data source. It returns a CustomListColumnCollection. Typically you perform a small pre-flight request here to determine the available columns and their types dynamically:
protected override CustomListColumnCollection GetColumnsOverride(CustomListData data)
{
return
[
new CustomListColumn("Fact", CustomListColumnTypes.String),
new CustomListColumn("Length", CustomListColumnTypes.Number),
];
}
External data types must be mapped to the Peakboard CustomListColumnTypes:
Peakboard type (CustomListColumnTypes) |
Common .NET / JSON mapping |
|---|---|
String |
string, JTokenType.String |
Number |
int, float, JTokenType.Integer, JTokenType.Float |
Boolean |
bool, JTokenType.Boolean |
Retrieving data: GetItemsOverride
GetItemsOverride is called when the actual data exchange takes place. It returns a CustomListObjectElementCollection. Each CustomListObjectElement consists of the column names and the actual values:
protected override CustomListObjectElementCollection GetItemsOverride(CustomListData data)
{
int maxLength = int.Parse(data.Properties["MaxLength"]);
CatFact myFact = GetRandomCatfact(maxLength).Result;
var items = new CustomListObjectElementCollection();
items.Add(new CustomListObjectElement { { "Fact", myFact.Fact }, { "Length", myFact.Length } });
return items;
}
Critical implementation rules
Caution!
- No
asyncoverrides. All override methods (GetDefinitionOverride,GetColumnsOverride,GetItemsOverride,SetupOverride,ExecuteFunctionOverride) must be declaredprotectedand cannot beasync. Resolve asynchronous work synchronously within them (e.g. by using.Resulton theTask). External calls can live in privateasynchelper methods as long as theirTaskis resolved synchronously in the override. - No unhandled exceptions. Wrap
GetColumnsOverride,GetItemsOverride,SetupOverrideandExecuteFunctionOverridecompletely intry/catch. Never rethrow inside thecatch– instead return a safe fallback value and additionally useLog.Error. - Only serializable values. In a
CustomListObjectElement, use only simple types (String,Number,Boolean) that match the declaredCustomListColumnTypes. Do not put complex objects (JToken/JObject/JArray/Exception) into cells, and avoidnullfor strings – use an empty string""instead.