---
title: "getSchemaAttribute"
method: GET
path: "/v1/entity/schemas/attributes/{composite_id}"
tags: ["Schemas"]
---

# getSchemaAttribute

`GET /v1/entity/schemas/attributes/{composite_id}`

Get a schema attribute from given attribute ID

## Path parameters

- `composite_id` string, required

## Response `200`

Success

- union
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'string', required
    - `multiline` boolean
    - `rich_text` boolean
    - `rows` union — Number of rows for rich_text textarea
      - integer
      - string
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'link', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'date' | 'datetime', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'country', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'boolean', required
    - `display_type` 'switch' | 'checkbox'
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'select' | 'radio', required
    - `options` union[]
      - union
        - object
          - `value` string, required
          - `title` string
        - string, nullable
    - `allow_any` boolean — Allow arbitrary input values in addition to provided options
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'multiselect' | 'checkbox', required
    - `disable_case_sensitive` boolean, nullable — controls if the matching of values against the options is case sensitive or not
    - `allow_extra_options` boolean, nullable — controls if the 360 ui will allow the user to enter a value which is not defined by the options
    - `options` union[]
      - union
        - string, nullable
        - object
          - `value` string, required
          - `title` string
    - `allow_any` boolean — Allow arbitrary input values in addition to provided options
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'status', required
    - `options` union[]
      - union
        - string, nullable
        - object
          - `value` string, required — The stored value of the option
          - `title` string — The displayed title of the option
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'sequence', required
    - `prefix` string — Prefix added before the sequence number
    - `start_number` integer
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'relation_user', required
    - `multiple` boolean
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'address', required
    - `default_address_fields` string[], nullable — Default fields visible on addresses Valid values are: - postal_code (default) - city (default) - street (default) - street_number (default) - plot_area - plot_of_land - suburb - country - postbox - additional_info - coordinates - start_date - end_date - salutation - title - first_name - last_name - name_suffix - company_name
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'relation_address', required
    - `default_address_fields` string[], nullable — Default fields visible on addresses Valid values are: - postal_code (default) - city (default) - street (default) - street_number (default) - plot_area - plot_of_land - suburb - country - postbox - additional_info - coordinates - start_date - end_date - salutation - title - first_name - last_name - name_suffix - company_name
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'relation_payment_method', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'currency', required
    - `currency_selector_only` boolean
    - `currency` object[], required — An array of currency configurations with a country code (ISO-4217)
      - `code` string, required
      - `description` string, required
      - `symbol` string, required
      - `flag` string
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'tags', required
    - `options` string[]
    - `suggestions` string[]
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'message_email_address', required
    - `address` string
    - `send_status` string
    - `email_type` string
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'number', required
    - `data_type` 'number' | 'string' — Optional data type override. When set to 'number', the value is stored as a number instead of a string. Defaults to 'string'.
    - `format` string
    - `show_separator` boolean — Whether or not to show a thousands separator
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'table', required
    - `columns` object[] — Column definitions for the table
      - `name` string, required — The column identifier (used as object key in row data)
      - `label` string, required — Display label for the column header
      - `type` 'string' | 'number' | 'date' | 'boolean' — The data type for cells in this column
      - `width` string — Optional column width (e.g., "100px", "20%")
      - `required` boolean — Whether this column is required for each row
      - `bold` boolean — When true, the row is rendered in bold (only applies in transposed mode)
    - `min_rows` integer — Minimum number of rows required
    - `max_rows` integer — Maximum number of rows allowed (or maximum periods when transposed)
    - `transposed` boolean — Enable transposed layout where rows become metrics and columns become periods
    - `column_header` object — Configuration for column headers in transposed mode
      - `template` string — Header label pattern with {{i}} as index placeholder (e.g., "Year {{i}}")
      - `start` integer — Starting index value for the template placeholder
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'consent', required
    - `topic` string, required
    - `identifiers` string[]
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'internal', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'ordered_list', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'image' | 'file', required
    - `multiple` boolean
    - `allowed_extensions` string[] — List of file extensions (without the dot suffix)
    - `display_images_landscaped` boolean — Controls how the images are presented to the user during upload on the Entity Details view.
    - `enable_description` boolean — When set to true, an i18n description will be used alongside the attribute label. This description should be set through the platform locales in the form: `file.{attribute_name}.description_text`.
    - `default_access_control` 'public-read' | 'private'
    - `file_size_bytes` integer — The maximum file size in bytes. Used to derive file_size and file_size_unit in the UI.
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string, required — Variable template used to format the computed value
    - `preview_value_formatter` string — Variable template used to format a preview for the computed value
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'computed', required
    - `computed` boolean
    - `amount_field` string — A source amount field that is used to compute the value of the attribute
    - `currency_field` string — A currency field used to format a computed currency value
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'partner_status', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'invitation_email', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'automation', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'internal_user', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'purpose', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'partner_organisation', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
    - `hidden` boolean — Do not render attribute in entity views
    - `show_in_table` boolean — Render as a column in table views. When defined, overrides `hidden`
    - `sortable` boolean — Allow sorting by this attribute in table views if `show_in_table` is true
    - `required` boolean
    - `readonly` boolean
    - `deprecated` boolean
    - `variant_overridable` boolean — Allow conditional variants of the entity to override this attribute's value. Only meaningful on schemas that declare `conditions`. Unflagged attributes stay fixed on the base entity.
    - `default_value` unknown
    - `group` string — Which group the attribute should appear in. Accepts group ID or group name
    - `order` integer — Attribute sort order (ascending) in group
    - `layout` string
    - `hide_label` boolean — When set to true, will hide the label of the field.
    - `icon` string — Code name of the icon to used to represent this attribute. The value must be a valid @epilot/base-elements Icon name
    - `render_condition` string — Defines the conditional rendering expression for showing this field. When a valid expression is parsed, their evaluation defines the visibility of this attribute. Note: Empty or invalid expression have no effect on the field visibility.
    - `data_classification` 'public' | 'pii' — Data classification of the attribute, used by anonymized responses (`?anonymize=true` or tokens minted with `anonymize: true`). - `pii`: the attribute value is always anonymized in anonymized responses (use to opt in free-text fields containing personal data) - `public`: the attribute value is never anonymized (use to opt out fields matched by built-in defaults, e.g. non-personal identifiers) When unset, built-in defaults apply based on the attribute type (email, phone, address, payment) and a curated list of well-known PII fields.
    - `_purpose` ClassificationId[]
    - `_manifest` string[], nullable — Manifest ID used to create/update the schema attribute
    - `constraints` object — A set of constraints applicable to the attribute. These constraints should and will be enforced by the attribute renderer.
    - `feature_flag` string — This attribute should only be active when the feature flag is enabled
    - `settings_flag` SettingFlag[] — This attribute should only be active when one of the provided settings have the correct value
      - `name` string — The name of the organization setting to check
      - `enabled` boolean — Whether the setting should be enabled or not
    - `value_formatter` string
    - `preview_value_formatter` string
    - `entity_builder_disable_edit` boolean — Setting to `true` disables editing the attribute on the entity builder UI
    - `protected` boolean — Setting to `true` prevents the attribute from being modified / deleted
    - `info_helpers` object — A set of configurations meant to document and assist the user in filling the attribute.
      - `hint_text` string — The text to be displayed in the attribute hint helper. When specified it overrides the `hint_text_key` configuration.
      - `hint_text_key` string — The key of the hint text to be displayed in the attribute hint helper. The key should be a valid i18n key.
      - `hint_custom_component` string — The name of the custom component to be used as the hint helper. The component should be registered in the `@epilot360/entity-ui` on the index of the components directory. When specified it overrides the `hint_text` or `hint_text_key` configuration.
      - `hint_tooltip_placement` string — The placement of the hint tooltip. The value should be a valid `@mui/core` tooltip placement.
    - `explicit_searchable` boolean — When set to true, this attribute will always be searchable regardless of the ELASTIC_MAX_SEARCH_FIELDS limit. Use this for critical search fields that must always be included in search operations.
    - `exclude_from_search` boolean — When set to true, this attribute will be excluded from search fields. Use this for fields that should not be matched during entity search operations, such as internal hashes or identifiers that might accidentally match search terms.
    - `repeatable` boolean — The attribute is a repeatable
    - `has_primary` boolean
    - `edit_mode` 'direct' | 'external' | 'approval' — Controls whether a write goes through immediately or is held as a pending entry on the parent entity's `_changesets` map. - `direct`: write applied immediately. No changeset created. - `external`: write held as a pending changeset; auto-cleared on a matching direct/ERP write. - `approval`: write held as a pending changeset; requires explicit human apply/dismiss. Used at two levels: per-attribute (entity-attribute changesets) and per-capability (currently the `meter_readings` capability on the Meter schema, gating reading submissions).
    - `edit_mode_config` EditModeConfig — Configuration for `edit_mode: external` auto-clear matching. Fields here (`match_strategy`, `fuzzy_config`) only take effect when `edit_mode` is `external`. They are ignored for `edit_mode: approval`, which never auto-clears and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints.
      - `match_strategy` 'exact' | 'fuzzy' | 'any' — Strategy for auto-clearing a changeset on an `edit_mode: external` attribute when a direct write (`?direct=true`) arrives — typically an ERP inbound sync. Ignored for `edit_mode: approval`, which does not auto-clear and is resolved exclusively via the `:apply` / `:dismiss` changeset endpoints. - `exact`: The inbound value must exactly match the proposed value (deep equality). - `fuzzy`: The inbound value is compared using the configured `fuzzy_config` algorithm. - `any`: Any update to the attribute clears the changeset, regardless of value.
      - `fuzzy_config` FuzzyConfig — Configuration for fuzzy auto-clear matching on `edit_mode: external` attributes. Not used for `edit_mode: approval`. Type compatibility with attribute shape is enforced at schema save time: - scalar string attributes: `suffix`, `digits_only`, `regex` - repeatable attributes: `set_equivalent`, `entry_match`, `ignore_fields`, `normalize_phone` - relation attributes: `relation_set`
        - `type` 'suffix' | 'digits_only' | 'normalize_phone' | 'ignore_fields' | 'set_equivalent' | 'entry_match' | 'relation_set' | 'regex', required — Which fuzzy algorithm to apply.
        - `suffix_length` integer — For type=suffix: number of characters to compare from end of string.
        - `fields_to_ignore` string[] — For type=ignore_fields and type=set_equivalent: field names to exclude when comparing array entries. `_id` is always stripped by the platform regardless of this config.
        - `regex_flags` string — For type=regex: flags to apply to the regex (e.g. 'i' for case-insensitive).
        - `country_code` string — For type=normalize_phone: country dialing code digits to strip (e.g. '49' for Germany). No '+' prefix.
        - `match_on` string — For type=normalize_phone: attribute key within array entries to compare on (e.g. 'phone_number').
        - `key` union — For type=entry_match: business key(s) within each entry used to match proposed entries against incoming entries.
          - string
          - string[]
        - `mode` 'subset' | 'exact_set' — For type=entry_match and type=set_equivalent: how strict the comparison is. - `subset` (default for entry_match): every proposed entry must exist in incoming; extra incoming entries are allowed. - `exact_set` (default for set_equivalent): the two sides must contain the same entries (order-insensitive, multiset semantics).
        - `ordered` boolean — For type=relation_set: when true, relation order is significant. Defaults to false (order-insensitive).
        - `require_tags_match` boolean — For type=relation_set: when true, each relation item's `_tags` must match on both sides (order-insensitive). Defaults to false — `_tags` are stripped before compare.
        - `pattern` string — For type=regex: regular expression pattern to test the incoming value against.
    - `type` 'portal_access', required
    - `composite_id` string
    - `schema` string — Schema slug the attribute belongs to
  - object — a readonly computed ID for the attribute including schema slug and the attribute ID
    - `id` string — ID for the entity attribute
    - `name` string, required
    - `label` string, required
    - `placeholder` string
- … truncated; see the full OpenAPI document linked below

## Other responses

- `404` — The requested resource was not found

---

[API](https://skmtc.net/epilot/apis/entity-api.md) · [All operations](https://skmtc.net/epilot/apis/entity-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/epilot/entity-api/versions/8dd3d44e1c4f/schema)
