Customization: Fields & Modules
Flash is shaped to each brand two ways, both on one shared code base — never a fork. Custom fields add your own data to the member record and are set through the v2 REST API. Modules are optional capabilities switched on per workspace and enforced by the server. This guide covers both.
Fields are declared before they're set
An owner or admin creates fields under Settings → Custom Fields. Each field has a key (its machine name, e.g. cf_membership_no), a type, and — for the select types — a list of options. The key and type are fixed once created. The API never creates fields; it only sets values for fields that already exist, and rejects unknown keys — the definition table is the allow-list.
Pass customAttributes on create or update
Both POST /api/v2/members (create) and PATCH /api/v2/members/{id} (update) accept a customAttributes object keyed by your field keys. Authenticate with a Bearer fl_live_ key that has the members:write scope.
curl -X POST https://flash.socialhub.ai/api/v2/members \
-H "Authorization: Bearer fl_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "ada@example.com",
"fullName": "Ada Lovelace",
"customAttributes": {
"cf_membership_no": "A-10023",
"cf_preferred_store": "flagship",
"cf_child_birthday": "2018-05-01"
}
}'On update, send only the keys you want to change. Setting a key to null clears it.
curl -X PATCH https://flash.socialhub.ai/api/v2/members/{id} \
-H "Authorization: Bearer fl_live_..." \
-H "Content-Type: application/json" \
-d '{ "customAttributes": { "cf_preferred_store": "airport" } }'What each field type accepts
| Type | Example JSON value | Accepts |
|---|---|---|
| text | "A-10023" | string |
| number | 42 | number (or numeric string) |
| date | "2018-05-01" | ISO date (YYYY-MM-DD) |
| boolean | true | true / false |
| enum | "flagship" | one of the field's options |
| list | ["running","tennis"] | subset of the field's options |
Validation is strict: a value must match its field's type, an enum/list value must be one of the defined options, and unknown keys are rejected with 400. Fields for sensitive personal data (PII) are not accepted yet — keep custom attributes to non-sensitive business values.
One value, used across the platform
Segments
Filter members by any custom field with type-appropriate operators — the same field you set over the API.
Email personalization
Reference the value in copy as {{cf_membership_no}} or {{member.cf_membership_no}}.
Member read
Custom values are returned on the member object under customAttributes.
Optional capabilities, switched on per workspace
Where a custom field adds a value, a module adds a whole capability — think a service-tickets module, appointments, or a repair log. Modules are off by default and enabled per workspace. Every workspace runs the same code base; a module being on or off is data (an entitlement), never a private build.
Enforced by the server, in one place
Each module has a stable key (e.g. tickets). Whether a workspace may use it is a single per-workspace switch, checked at one judgment point and applied everywhere the module appears — fail-closed: if the switch isn't on, the capability simply isn't there.
API
A disabled module's endpoints reject calls with 403. Access is never left to chance in the UI alone.
Navigation & pages
A module's menu entries and pages appear only when it's enabled for the workspace — and disappear cleanly when it's turned off.
Tenant-isolated
Entitlements are per workspace. One brand's modules and data are never visible to another.
How a new module is introduced
When a capability is genuinely reusable, it's built once as a module — registered in a module catalog under its key, with its own data, its own entitlement-gated API and its own pages. The first workspace that needs it gets it built; the next just flips the switch. This is the core of the model: customer differences are expressed as settings, so one upgrade or fix reaches every workspace at once.
- The module registers in the catalog with a stable key and description.
- Its data and API routes are gated on that key (fail-closed).
- Its navigation and pages are shown only when the key is enabled.
- An owner turns it on for a workspace; a second workspace is a switch, not a rebuild.
Turn modules on or off
Workspace owners manage modules from Settings → Modules. Each toggle takes effect immediately across the API and the UI.
The decision rule: use configuration first; add a custom field when you need to store a value; build a module when a capability is genuinely reusable — and never fork the product for a single customer.
Need a whole new kind of record, not just an extra field? See Developer Extensibility — no-code custom objects, event webhooks, and Zapier / Make connectors that extend Flash without a fork.