> For the complete documentation index, see [llms.txt](https://docs.eximee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.eximee.com/documentation/documentation-en/budowanie-aplikacji/model-danych/struktura-modelu-danych.md).

# Data model structure

## Tree structure

{% columns %}
{% column %}
The data model has a tree structure that makes it easier to map the hierarchical structure of business domain objects.

**Leaves** of the tree represent the most detailed element of the structure. Leaves, called fields, no longer have any subordinate elements (children) and represent a single data field. Examples include "customer name" or "bank account number".

**Nodes** of the tree represent objects made up of other objects and/or fields. Examples: "correspondence address", "customer income".
{% endcolumn %}

{% column %}

<figure><img src="https://2112972046-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2FpN14hRagp8jodNrtEt5Q%2Ftree_structure.png?alt=media&amp;token=512337b9-4e0e-4ad3-982f-cbc14fff00f3" alt="" width="216"><figcaption><p><em><strong>Figure 1.</strong> Tree structure</em></p></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

{% hint style="info" %}
It is possible to change the order of nodes and leaves in the tree by holding and dragging them. Reordering is possible only within the same hierarchy level and while working on a draft version. This modification is visual and does not affect the model's logic.
{% endhint %}

### Nodes

Each data model node has the following attributes:

* a key unique among its siblings (descendants of the same node)
* cardinality expressed by the formula `n..m` meaning from `n` occurrences at minimum to `m` at maximum, e.g.:
  * `1..1` - the object occurs only once
  * `0..1` - the object is optional
  * `1..null` - the object occurs at least once, with no limit on the maximum number of occurrences
* description of the object's meaning for the application

{% hint style="info" %}
Nodes can therefore be uniquely identified using a key formed by concatenating the keys of parent nodes, e.g.: `client.email`.
{% endhint %}

### Leaves

In addition to node attributes, leaves also have:

* data sources - determine how and from where the value is retrieved
* default value - what the field returns if none of the data sources returns a value

A field can have a defined list of data sources. Resolving the field value consists of calling the data sources in the order they are defined until a non-empty value is obtained. Thus, the first source returning a non-empty value wins.

We can retrieve data from the model only for selected individual keys, i.e. we cannot retrieve the values of keys that have children underneath them, just as we cannot retrieve the entire model in a single request.

### Field value type (typing)

{% hint style="info" %}
The type catalog is optional and configured separately for each platform deployment. If it has not been configured, the editor does not display value-type badges, and field values are not validated against the type.
{% endhint %}

The type catalog allows you to define the field value type: **text**, **date** or **date and time**. The data model editor shows it next to the field name as a badge. If the catalog defines the field as multiple, the badge **Array**is displayed instead of the value type. When a node's multiplicity in the model does not match the catalog, the badge is struck through and marked with a warning icon.

The "Field outside schema" label appears only for a key whose name does not appear in the type catalog at a given level. A key with a known name retains the badge resulting from the catalog, even if its multiplicity is inconsistent.

<figure><img src="https://2112972046-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-3cd1fe8be375aad9047232f2160cafd5080c3499%2FrodzajWartosciPola.png?alt=media" alt="Typ pola"><figcaption><p><em><strong>Figure 2.</strong> Badge example</em></p></figcaption></figure>

{% hint style="info" %}
The badges are informational. A mismatch between the model structure and the type catalog, for example a different key multiplicity, does not block data model publication.
{% endhint %}

#### Validation of values on save

The value saved in a field covered by the type catalog must match the declared type:

* **On the form** - when attempting to proceed, a field mapped to a typed key reports the error "The entered value has an invalid format" if the entered value cannot be recognized as the declared type.
* **In ScriptCode** - saving an incompatible value through the data model API is rejected; the value is not saved.

> Example: a field mapped to a key of type **date and time** will reject the value `yesterday`, but will accept `2026-09-15` or `2026-09-15T10:00:00Z`. An empty value passes validation regardless of the field type.

<figure><img src="https://2112972046-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-7a21da17bb836d3ad85e411b1fb9655490e6ac38%2FnieprawidlowyFormatPola.png?alt=media" alt="Nieprawidłowy format"><figcaption><p><em><strong>Figure 3.</strong> Error returned for a value inconsistent with the field type</em></p></figcaption></figure>

#### Maximum text length from the type

A text field mapped to a key in the type catalog is subject to the length limit specified there. A limit set explicitly in the component may be lower, but it cannot increase the limit resulting from the catalog.

#### Displaying in the case list

If the value stored under a typed key does not match the declared type, the case list displays "Data error" instead. This may apply, for example, to a value saved before validation was enabled. The case remains visible, and the other columns are displayed normally. If the field has an accepted mask in the depersonalization process, the case list displays it instead of the "Data error" message.

## Arrays in the data model <a href="#strukturamodeludanychbudowanieiuzywanie-definiowanietablicowychpolmodeludanych" id="strukturamodeludanychbudowanieiuzywanie-definiowanietablicowychpolmodeludanych"></a>

Model nodes marked as multiple (maximum cardinality `>1`) create an array of simple values (for fields) and complex objects (for nodes that are not leaves). It is also possible to define nested collections.

### Keys and identifiers <a href="#strukturamodeludanychbudowanieiuzywanie-kluczeiidentyfikatory" id="strukturamodeludanychbudowanieiuzywanie-kluczeiidentyfikatory"></a>

When referring to data model nodes defined as an array (or being descendants of an array), you must always use array notation:

* array\[].field - retrieves all occurrences of the field; depending on the API used, it will return a collection or a single string with the "," separator
* array\[0].field - retrieves a single value resolved by the collection row indicated in the key (in the example, 0 means the first element of the array),
* array.field - will cause an error; it is not possible to refer to an array node without array notation,

### Defining an array <a href="#strukturamodeludanychbudowanieiuzywanie-definiowanietablicywmodeludanych" id="strukturamodeludanychbudowanieiuzywanie-definiowanietablicywmodeludanych"></a>

To define an array field, it is necessary that:

* the multiple data model node must have a cardinality greater than `multiplicityMax=1`, e.g. `1..null`,
* the multiple data model node must have defined sources pointing to an array; the indexes of this collection will be used to index repetitions of the model value,
* nodes below a multiple data model node can use the mapped index of the iterated model node to point to specific elements of the service output,
  * the parent node will always expose its current index in the execution context (while resolving values for a collection) under the identifier *`nodeNameIdx`,*
  * fields iterated by the parent should point to objects within the collection iterated by the parent,
  * however, this is not strictly necessary; it is possible to use this index to iterate over a completely different field or to extract fields that are not arrays at all.

{% hint style="info" %}
For example, having a service result consisting of a fixed field and two arrays - known to have the same length (arrayA, arrayB, fieldC) - it is possible to create a mapping in which the model iterates over arrayA, while its subfields extract successive fields from arrayB and the fixed value from fieldC.
{% endhint %}

## Binding a provider to the data model

A provider is a local data source written in [ScriptCode](https://docs.eximee.com/budowanie-aplikacji/logika-biznesowa/scriptcode/wprowadzenie-do-scriptcode), which defines how to obtain values for model fields. It can be used by fields to supply their values. The data source can be a function:

* script-based,
* calling an external REST service,
* referencing another element of the model,
* retrieving a value from the application configuration.

The provider described below is **a data source for a data model leaf**. It is used to retrieve the current currency exchange rate from an external API (NBP):

* `exchangeRate` is **a leaf (field)** in the tree,
* the field has no children and represents a single value (currency exchange rate),
* it can be nested in a node, e.g.: `exchangeRates.exchangeRateEUR`.

<figure><img src="https://2112972046-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-74883de5f437263604a380103f4f7162dfe2e315%2FkodProvidera.png?alt=media" alt="przykład z kodem providera"><figcaption><p><em><strong>Figure 4.</strong> Example of a provider retrieving the current currency exchange rate from an API (NBP)</em></p></figcaption></figure>

Workflow:

* the key, i.e. the currency code (`currencyCode`), e.g. "EUR" or "USD", is retrieved from the provider's input parameters,
* this value is passed to the provider from the data model,
* the provider performs a GET request to the configured endpoint `nbpExchangeRate` using `api.rest.v1.get`,
* path parameters (`pathParams`) build the request address in the form: `/rates/A/{currencyCode}` (the letter "A" denotes the table of average exchange rates published by the NBP),
* the API response contains an object `body`, which contains the array `rates`, and the first element of the array is retrieved (`rates[0]`), then its field `mid`, which represents the average exchange rate,
* the provider returns an object containing the field `exchangeRate`, the value of this field corresponds to the retrieved currency exchange rate and can be further used in the data model or form.

### Configuring data sources for a field

Each field in the data model has the ability to define **data sources**.\
Configuration is available by clicking the pencil icon next to the selected field, which opens the settings drawer for data sources associated with that field. If data sources have already been defined for a given key, their names are visible in the panel - in the example shown this is `exchangeRateFromNBPProvider`. After selecting a source, you can configure input parameters and output mapping.

<figure><img src="https://2112972046-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-a86d2faadc46924920ac10b4eee1c1654cadf497%2FzrodlaDanychParametryMapowanie.png?alt=media" alt="przykład z kodem providera"><figcaption><p><em><strong>Figure 5.</strong> Example of using a provider as a data source in the model</em></p></figcaption></figure>

In the **Parameters** tab, the values passed to the provider are defined.\
In the described case:

* key: `currencyCode`
* value: `EUR`

This parameter is used by the provider to call the external API.

In the **Mapping** section, it is specified which data from the provider's response will be assigned to the field in the model. In this example, the value `exchangeRate`.

The obtained value can then be used in the data model or directly in the form. More about using the data model on the application in the tab [Data model on the interface](https://docs.eximee.com/~/revisions/6RARJsssdz6tDsOideLu/budowanie-aplikacji/interfejs-uzytkownika/formularze/praca-z-komponentami-bazowymi/model-danych-na-interfejsie).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.eximee.com/documentation/documentation-en/budowanie-aplikacji/model-danych/struktura-modelu-danych.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
