> For the complete documentation index, see [llms.txt](https://mercure-technologies.gitbook.io/xprem/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mercure-technologies.gitbook.io/xprem/identity/overview.md).

# Overview

By default, a xprem server maintains a registry of the devices running your app. Every install gets one row, created and enriched from requests the app already makes.\
\
Nothing needs to be integrated in the app for the basics, and nothing personal is collected unless you explicitly attach it yourself.

The registry is fed by two kinds of touchpoints: the manifest endpoint that every expo-updates client already polls, and the telemetry endpoints used by apps that embed expo-observe.

### The EAS Client ID

Everything in Identity is keyed by the EAS Client ID, a random UUID that your app generates the first time the app launches and then keeps on the device.\
\
The updates client sends it with every request in the `EAS-Client-ID` header, and expo-observe stamps it on every telemetry batch as the `expo.eas_client.id` resource attribute.

The EAS Client ID identifies an installation, not a person. It carries no account, no hardware serial and no advertising identifier, it cannot be looked up anywhere outside your own server, and reinstalling the app produces a new one.

xprem uses it as the primary key of the device registry and never links it to anything else on its own; if you want a device row to mean "this customer", you do that deliberately through custom attributes.

### Touchpoint 1: the manifest endpoint

Every app built with expo-updates polls `/manifest` to ask whether a newer update exists for its channel and runtime version. The poll happens when the app launches (with the default `checkAutomatically` setting) and whenever your code calls `Updates.checkForUpdateAsync()`.

It is part of the Expo Updates protocol itself, so this touchpoint exists for every app served by xprem, with no extra dependency.

Each poll is recorded as a check-in for the device:

* **Existence and liveness**: the first-seen and last-seen timestamps. Last-seen bumps are debounced to at most one write per device per minute, and the dashboard counts a device as online when it checked in within the last 20 minutes.
* **The update the device is running**, from the `expo-current-update-id` header. When that update is one the server knows, it also resolves the branch, runtime version and platform shown in the inventory.
* **Launch-failure signals**: the `expo-fatal-error` and `Expo-Recent-Failed-Update-Ids` headers. They feed update health, so a release that crashes at startup becomes visible instead of silently disappearing from the stats.
* **The device's location**, when the server is configured for geolocation (see )

### Touchpoint 2: the telemetry endpoints

Apps that embed expo-observe ship their logs and metrics to `POST /observe/{appId}/{projectId}/v1/logs` and `.../v1/metrics`. Log batches enrich the same device rows whether or not ClickHouse is configured; metric batches are only read when ClickHouse is set up, and are acknowledged and dropped otherwise.

From telemetry, Identity additionally learns:

* **Hardware and OS**: the device model and the OS name and version, from the batch's resource attributes.
* **The binary version** of the app, from the `service.version` attribute.
* **Fresher update-health state** between manifest polls, since every batch also names the update the device is running, and JS crash events count against that update's health.
* **Custom attributes (only for enterprise users)**: the `$set`, `$set_once` and `$unset` events on the logs endpoint let your app attach its own metadata to the device row, against a key allowlist you declare in the dashboard. The registry itself works in every edition; storing custom attributes requires an active enterprise license.

### What is collected where

| Data                                                                            | `/manifest` | `/logs` and `/metrics` |
| ------------------------------------------------------------------------------- | ----------- | ---------------------- |
| First and last seen                                                             | Yes         | Yes                    |
| Current update, branch, runtime version, platform                               | Yes         | Yes                    |
| Launch failures and crash details                                               | Yes         | Yes (JS crash events)  |
| Device model, OS name and version                                               | No          | Yes                    |
| App binary version                                                              | No          | Yes                    |
| Custom attributes (`$set`, `$set_once`, `$unset`) **Only for enterprise users** | No          | Yes (`/logs` only)     |
| Location, when configured                                                       | Yes         | Yes                    |

Without ClickHouse configured, only `/logs` batches are read: the `/metrics` contributions in this table require it.

### Opting out

Set `DISABLE_DEVICE_TELEMETRY=true` to opt out entirely: manifest check-ins, identity operations and telemetry batches are all dropped, nothing is recorded about any device, and the Observe and Identity sections of the dashboard report the feature as unavailable.


---

# 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://mercure-technologies.gitbook.io/xprem/identity/overview.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.
