Custom Entities
Overview
Custom Entities let you introduce new record families into tSM that behave like native records across the platform: they have their own API resource path, can be rendered in listings and detail pages, and can own Supporting Entities (attachments, comments, worklogs, …) via the standard ownership model. (tSM APP)
Custom Entities are based on the same foundational building blocks already used throughout tSM:
- EntityType as the canonical "class of records" registry (e.g.,
Customer,Ticket,Order,Attachment) used for routing, UI composition, and cross-module links. (tSM APP) - EntitySpecification (Configuration Profile) + Characteristics to define dynamic attributes, forms, rules, and indexing behavior. (tSM APP)
- Supporting Entities using
ownerType+ownerIdto attach reusable "side entities" to any record. (tSM APP)
Key terms
CustomEntity
A record family registered in EntityType that is marked as a Custom Entity. EntityType.code becomes the stable identifier used by:
- API routing and discovery,
- UI composition (widgets, icons),
- ownership and references (
ownerType,refType). (tSM APP)
CustomEntityType
A "type catalog" for a Custom Entity (e.g., CableType for Cable). A CustomEntityType record points to EntitySpecification, which defines:
- characteristics (dynamic fields),
- new/detail forms,
- behavior rules. (tSM APP)
Shared vs type-specific configuration
tSM supports:
- entity-level shared attributes (apply to all records of a CustomEntity),
- type-specific attributes (apply only to a selected CustomEntityType).
This is implemented by combining:
- an optional shared EntitySpecification configured at the CustomEntity level, and
- the EntitySpecification referenced by the selected CustomEntityType.
How Custom Entities integrate with tSM core
EntityType is the anchor for routing, UI composition, and ownership
EntityType is explicitly described as the canonical classification of records and the basis for:
- cross-module linking (
ownerType/refType), - discoverability & routing (ties records to a microservice and public API),
- presentation (icons and UI widgets). (tSM APP)
Because Supporting Entities use the universal ownerType + ownerId pattern, any record family that exists as an EntityType (including a Custom Entity) can own attachments/comments/worklogs immediately. (tSM APP)
Microservice and Module provide deployment + domain grouping
- Microservice Registry stores deployment inventory metadata, including a gateway-relative
backendUrlused by UIs and tools. (tSM APP) - Module groups what users experience around a business domain (forms, processes, listings, widgets) and points to the primary microservice powering that domain. (tSM APP)
Configuration guide
This section is written for configurators who want to add a new Custom Entity end-to-end.
1) Choose where the Custom Entity will live (Microservice)
Ensure a Microservice entry exists for the runtime hosting Custom Entities and that it has a correct gateway-relative backendUrl. (tSM APP)
Microservice example
{
"code": "tsm-dynamic",
"name": "Dynamic Runtime",
"backendUrl": "tsm-dynamic/api",
"dataTags": ["core", "dynamic"]
}
Good practices for Microservice (stable code, gateway-relative backendUrl, minimal config) are documented in the Microservice Registry chapter. (tSM APP)
2) Create/choose a Module (optional but recommended)
Use a Module to group the Custom Entity into a clear business domain (navigation, governance, rollout, filters). Modules are "purpose-oriented building blocks" that group user-facing domain elements. (tSM APP)
Module example
{
"code": "NETWORK_ASSETS",
"name": "Network Assets",
"primaryMicroservice": "tsm-dynamic",
"dataTags": ["network", "assets"]
}
3) Register the Custom Entity in EntityType
Create an EntityType entry for the Custom Entity (example below uses Cable, which is a common real-world case for rich evidence, attachments, and maintenance worklogs).
EntityType attributes (microservice routing, optional public API URL override, UI hints) are documented in the EntityType chapter. (tSM APP)
EntityType example: Cable
{
"code": "Cable",
"name": "Cable",
"microservice": "tsm-dynamic",
"publicApiUrl": "cables",
"defaultCardProfile": "cable-detail",
"listingCardWidget": "GenericEntityCard",
"icon": "cable",
"type": "CustomEntity",
"customEntity": {
"customEntityTypeCode": "CableType",
"sharedEntitySpecificationId": "ESPEC.CABLE.COMMON",
"search": { "enabled": true, "indexAlias": "cable" }
},
"dataTags": ["network", "custom"]
}
Notes:
publicApiUrlis relative toMicroservice.backendUrl. If not set, EntityType supports deriving it from the code (kebab-case, plural). (tSM APP)- Keep
EntityType.codestable: it becomes a key in references (ownerType,refType), configs, and routing. (tSM APP)
4) Register the corresponding CustomEntityType family in EntityType
Create a second EntityType entry for the CustomEntityType records.
EntityType example: CableType
{
"code": "CableType",
"name": "Cable Type",
"microservice": "tsm-dynamic",
"publicApiUrl": "cable-types",
"defaultCardProfile": "cable-type-detail",
"listingCardWidget": "GenericTypeCard",
"icon": "tag",
"type": "CustomEntity",
"customEntity": { "role": "CustomEntityType" },
"dataTags": ["network", "custom", "types"]
}
5) Create EntitySpecifications (shared + per-type)
tSM's characteristics model is based on EntityType + Configuration Profiles (EntitySpecification) + Characteristics, where EntitySpecification carries the dynamic attribute definitions and the form specification used for rendering and validation. (tSM APP)
Recommended structure:
-
Shared spec:
ESPEC.CABLE.COMMONCommon fields for all cables (e.g., location, owner organization, installation date, documentation link). -
Type specs: e.g.
ESPEC.CABLE.FIBER_TRUNK,ESPEC.CABLE.COPPER_DROP, … Fields specific to that cable subtype.
6) Create CustomEntityType records (the "type catalog")
Create records of entity type CableType, each referencing its type-specific EntitySpecification and pointing back to the owning CustomEntity (entityTypeCode = "Cable").
CableType example record
{
"entityType": "CableType",
"entityTypeCode": "Cable",
"code": "FIBER_TRUNK",
"name": "Fiber trunk cable",
"entitySpecificationId": "ESPEC.CABLE.FIBER_TRUNK"
}
7) (Optional) Menu items for UI navigation
EntityType provides presentation hints (icon, listing widget, card profile). (tSM APP) For explicit navigation entries in the left menu, add Menu Items that route to:
/cables(instances)/cable-types(types)
(Exact router links depend on your UI routing conventions.)
Data model diagram
API behavior
Public API path and service routing
EntityType ties a record family to:
- a microservice (
EntityType.microservice), and - a public API path (
EntityType.publicApiUrl) that is relative to the microservicebackendUrl. (tSM APP)
tSM Public API documentation describes the platform as modular and microservice-based, with consistent REST operations per module. (tSM APP)
Typical endpoints (Cable):
GET /cablesPOST /cablesGET /cables/{id}PATCH /cables/{id}
Type endpoints:
GET /cable-typesPOST /cable-typesPATCH /cable-types/{id}
Creating a Custom Entity record
Create Cable example payload
{
"typeCode": "FIBER_TRUNK",
"name": "Brno – Pohořelice trunk #12",
"statusCode": "ACTIVE",
"characteristics": {
"fiberCount": 96,
"sheathType": "PE",
"installedAt": "2024-10-14",
"vendor": "ACME Cables"
}
}
The selected typeCode determines the CustomEntityType record, which determines the EntitySpecification and therefore the characteristics schema and UI behavior. (tSM APP)
Supporting Entities with Custom Entities
Supporting Entities (Attachment, Comment, Worklog, …) share a universal ownership model based on ownerType and ownerId. (tSM APP)
Because ownerType is the "type/class of the parent record" (e.g., Ticket, Customer, …), a Custom Entity can be used as an owner by setting ownerType = "<EntityType.code>". (tSM APP)
Attachment example (SpEL)
The Supporting Entities documentation shows an Attachment created by @attachmentPublicService.create(...) with ownerType and ownerId. (tSM APP)
@attachmentPublicService.create({
"ownerType": "Cable",
"ownerId": #cable.id,
"attachmentType": "Report",
"name": "OTDR_2026-01-05.pdf",
"data": #file.encodeBase64()
})
Worklog example (SpEL)
Worklogs follow the same ownership pattern and are created with @worklogPublicService.create(...). (tSM APP)
@worklogPublicService.create({
"ownerType": "Cable",
"ownerId": #cable.id,
"worklogType": "Investigation",
"duration": 1.5,
"description": "Measured attenuation and compared with baseline."
})
Best practices
- Keep
EntityType.codestable. It is used in references (ownerType,refType), configs, and API routing. (tSM APP) - Prefer derived
publicApiUrlunless you need an override, and keep it relative toMicroservice.backendUrl. (tSM APP) - Use
dataTagsconsistently on Microservice, Module, and EntityType for filtering and governance. (tSM APP) - Keep
config/customEntitylightweight (feature flags, UI hints, routing knobs). Microservice and EntityType docs explicitly positionconfigas "small configuration," not deployment configuration. (tSM APP) - Avoid characteristic name conflicts within the same EntityType. The Characteristics documentation notes that within the same EntityType, characteristics with the same attribute name must be identical for consistent interpretation across specifications. (tSM APP)
Troubleshooting checklist
The entity does not appear in UI
- Verify
EntityType.validityFrom/To(or derivedvalid) allows it to be active. (tSM APP) - Verify
EntityType.microservicepoints to an existing Microservice and that MicroservicebackendUrlis set. (tSM APP) - Ensure UI hints are set (
listingCardWidget,defaultCardProfile,icon) for consistent rendering. (tSM APP)
API returns 404 on /cables
- Confirm
publicApiUrl(or its derived value) matches the path you're calling. (tSM APP) - Confirm Microservice
backendUrlis correct and reachable behind the gateway. (tSM APP)
Type selection fails / characteristics validation fails
- Confirm the referenced EntitySpecification exists and includes the Characteristics schema and forms as expected. (tSM APP)
- Check that shared and type-specific specs do not define conflicting characteristics under the same
attributeNamefor the same EntityType. (tSM APP)
See Also
- Form — JSON Schema definitions backing characteristics.
- Characteristics — dynamic attributes used by Custom Entities.
- Entity Specification — Configuration Profiles grouping characteristics for entity subtypes.
- EntityType — the canonical entity classification registry.
- Entities & Characteristics (Architecture) — conceptual overview.