Pass Custom Fields
Custom fields are arbitrary key/value data used to personalize passes and drive segmentation. They are stored on the client (clients.custom_fields), not on the pass — every pass reads them from its related client.
Where things live
- Reading/writing values for a specific client: use the Clients endpoints (
wh.clients.updateCustomFields(...)). - Defining the field schema for a workspace: use the workspace data model (
wh.workspaces.createDataModelField(...)). - Discovering which fields and values are in use: the two dedicated discovery endpoints documented below.
Discover Custom Field Names
GET /wallethero-api/passes/custom-fields?workspace_id=:workspaceId
Returns the list of non-system custom field names defined in the workspace data model, ordered by their configured sort order.
Auth: Bearer token — member of the workspace (membership is derived from the workspace_id query parameter).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspace_id | string (UUID) | Yes | Workspace identifier |
Example Request
curl "https://api.wallethero.app/wallethero-api/passes/custom-fields?workspace_id=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_TOKEN"Response (200)
{ "data": ["tier", "points", "member_since", "store_preference"] }SDK
const fieldNames = await wh.segments.getCustomFieldNames("WORKSPACE_ID");
// => ["tier", "points", "member_since", "store_preference"]Discover Custom Field Values
GET /wallethero-api/passes/custom-fields/:fieldName/values?workspace_id=:workspaceId&limit=:limit
Returns the distinct values stored for a single custom field across the workspace's clients, with occurrence counts and a isNumeric flag. Useful for building dynamic segment filters.
Auth: Bearer token — member of the workspace (derived from the workspace_id query parameter).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
fieldName | string | Custom field name. Must match ^[a-zA-Z_][a-zA-Z0-9_]*$ |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
workspace_id | string (UUID) | Yes | — | Workspace identifier |
limit | number | No | 50 | Max distinct values to return (capped at 100) |
Example Request
curl "https://api.wallethero.app/wallethero-api/passes/custom-fields/tier/values?workspace_id=WORKSPACE_ID&limit=50" \
-H "Authorization: Bearer YOUR_TOKEN"Response (200)
{
"data": [
{ "value": "Gold", "count": 412, "isNumeric": false },
{ "value": "Silver", "count": 890, "isNumeric": false },
{ "value": "Bronze", "count": 1503, "isNumeric": false }
]
}SDK
const values = await wh.segments.getCustomFieldValues("WORKSPACE_ID", "tier", 50);
// => [{ value: "Gold", count: 412, isNumeric: false }, ...]Supported Data Types
| Type | Description | Example |
|---|---|---|
string | Text value | "Gold", "[email protected]" |
number | Integer or decimal | 1500, 99.99 |
boolean | True/false | true, false |
date | ISO date string | "2024-01-15" |
array | Array of strings (multiselect) | ["sports", "music"] |
Setting Custom Fields
Custom fields are written on the client. They propagate to every pass that client holds.
// On pass creation, via client_identity (auto-create/reuse the client)
await wh.passes.create({
pass_template_id: "TEMPLATE_ID",
project_id: "PROJECT_ID",
workspace_id: "WORKSPACE_ID",
client_identity: {
email: "[email protected]",
custom_fields: { points: 0, tier: "Bronze", member_since: "2024-01-15" },
},
});
// Later, update (merged with existing values)
await wh.clients.updateCustomFields("WORKSPACE_ID", "CLIENT_ID", {
points: 1500,
last_purchase: "2024-01-15",
});
// Remove a field by setting it to null
await wh.clients.updateCustomFields("WORKSPACE_ID", "CLIENT_ID", {
temporary_promo: null,
});Displaying Custom Fields
Reference field values in pass template field definitions:
{
"front_fields": [
{ "label": "Member", "value": "{{first_name}} {{last_name}}" },
{ "label": "Points", "value": "{{points}}" },
{ "label": "Status", "value": "{{tier}}" }
]
}Defining a Data Model
For consistent fields (and to make them appear in getCustomFieldNames), define them on the workspace data model:
await wh.workspaces.createDataModelField("WORKSPACE_ID", {
field_name: "tier",
field_label: "Membership Tier",
field_type: "string",
default_value: "Bronze",
allowed_values: ["Bronze", "Silver", "Gold", "Platinum"],
});Best Practices
- Use consistent field names across all clients in a workspace.
- Define a data model so fields show up in discovery endpoints and validation runs.
- Use appropriate types — numbers for numeric values, not strings.
- Keep structure flat — avoid deeply nested objects.
- Choose filterable names — discovery endpoints and segment filters key off the field name.