> 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/logika-biznesowa/scriptcode/script-code-bazy-projekcji.md).

# Managing projection databases (Registry)

### Eximee Registry API in ScriptCode

API `api.registry.v1` is used to save, update, and read data in the projection cache database.

Thanks to full integration with the platform engine, you can use the Registry API directly in JavaScript code:

* **In the context of the user interface (form):** In validation scripts, page services (PageService), and entry/exit scripts (EntryService, ExitService).
* **In the context of process automation:** In script tasks [ScriptCode Tasks](/documentation/documentation-en/budowanie-aplikacji/logika-biznesowa/scriptcode/zadanie-skryptowe-scripttask.md) and [event consumers from Kafka/MQ](/documentation/documentation-en/eksploatacja-aplikacji/obsluga-zdarzen/konsumenci-kafka.md).

The values to be saved can be computed in form services (EntryService, PageService...) or retrieved directly from the application's data model (`api.model.v1.get()`). Search results can be dynamically presented to the user on the screen or used in algorithms, e.g. to verify visibility conditions.

### API

The table below contains a description of the interface methods and parameters `api.registry.v1`

| Method      | Arguments                                                    | Return type          | Description                                                                                    |
| ----------- | ------------------------------------------------------------ | -------------------- | ---------------------------------------------------------------------------------------------- |
| save        | namespace: String, id: String, data: String                  | void                 | Saves or updates (upserts) text data under the specified identifier in the selected namespace. |
| saveVersion | namespace: String, id: String, data: String, version: String | void                 | Saves data with explicit specification of its schema version.                                  |
| get         | namespace: String, id: String                                | String               | Retrieves and returns the stored string for the given namespace and identifier.                |
| getVersion  | namespace: String, id: String                                | TempStoreVersionItem | Retrieves an object containing both the data model and the schema version.                     |
| delete      | namespace: String, id: String                                | void                 | Permanently deletes the entry with the specified identifier from the selected namespace.       |

#### Handling JSON format (data)

Since the save methods accept and return data as a string (String), JavaScript scripts should use object serialization and deserialization:

* **When saving (save / saveVersion):** The passed JavaScript object should be converted to text using JSON.stringify(object).
* **When reading (get):** The retrieved text should be parsed into an object using JSON.parse(string).

#### TempStoreVersionItem

The object returned by the getVersion method has properties (getters) available directly in JavaScript:

* data (String) – Raw string with the stored data model.
* version (String) – Assigned schema version.

### The meaning of the namespace (*namespace*)

The namespace parameter is not a rigid dictionary imposed by the Eximee platform. It gives the low-coder full freedom to define logical domains for storage and search (so-called context-bounded domains).

You can treat it as an autonomous address space – any string defined by you that logically groups related entries. This gives us:

* **Data separation:** The same low-code application can save different aspects of the same case to separate domains (e.g. "MortgageLoan\_Application", "MortgageLoan\_Collateral", "MortgageLoan\_Scoring"), which makes permission management and data readability easier.
* **No collisions:** Different applications can use exactly the same identifiers (e.g. the same PESEL number), because their data is isolated within their own namespaces.
* **Flexible search:** When searching for information using the get method, you query only the selected, precisely defined domain, which guarantees lightning-fast response times from the projection database.

### Business key selection strategy

Before saving data, you must determine the primary key (`id`), which will uniquely identify the record in the projection database. The registry does not impose a rigid format – the key can be any unique string.

Common scenarios are:

* **PESEL or CIF of the client:** When you want to aggregate and verify requests associated with a given person (e.g. blocking multiple applications).
* **Company NIP or REGON:** When you want to link cases concerning a given company.
* **Bank account number:** When there is a need to link different processes modifying account parameters
* **Shopping cart / transaction identifier (basketId):** When the case concerns a group of products processed together.
* **Composite key:** A dynamic combination of several parameters (e.g. PESEL\_PRODUCTCODE) created in a script.

### Example: Limiting the number of simultaneous credit processes to 1

We want to control the number of a client's credit applications and limit it to one. If the client tries to start a second application, they will receive a message requiring them to finish the previous application or be automatically redirected to the application started earlier.

#### Recording the fact of applying for a loan (Initialization)

Script most often attached to the action of moving to the next page or clicking the "Send" button:

```javascript
// Record the fact of applying for a cash loan
api.registry.v1.save(
    "CashLoan",                // namespace
    api.model.v1.get("klient.pesel"), // PESEL from the data model as the identifier
    JSON.stringify({                  // In the data, you can pass anything you need
        businessKey: api.model.v1.get("businessKey"), 
        amount: api.model.v1.get("kredyt.kwota"),  
        status: "new"
    })
);
```

#### Verification and blocking of multiple applications.

Script run on form entry (EntryService), checking whether the client already has an active application in progress:

```javascript
// Search for active applications for the PESEL from the data model
const istniejacyProces = api.registry.v1.get("CashLoan", api.model.v1.get("klient.pesel");

// If an active process is found, set a blocking message on the form
if (!istniejacyProces) {
    // We block the client's ability to continue applying
} else {
    // We grant the client a loan
}
```

#### Removing information about the active process

Script run at the completion of application processing, e.g. as a ServiceTask

```javascript
api.registry.v1.delete("CreditApplication", api.model.v1.get("klient.pesel"));
```


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.eximee.com/documentation/documentation-en/budowanie-aplikacji/logika-biznesowa/scriptcode/script-code-bazy-projekcji.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
