> For the complete documentation index, see [llms.txt](https://docs.mediarithmics.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mediarithmics.io/setup-and-monitor/collect-and-manage-your-data/import-data-in-batch/enrich-users-with-identifiers.md).

# Enrich users with identifiers

Declare that several identifiers belong to the same person, and merge their UserPoints.

## Your goal

Tell the platform what your own systems already know: that a hashed email, an account ID, and a device identifier are the same person - so their histories become one.

## Expected outcome

One UserPoint carrying all the identifiers on each line of your file, with the previously separate UserPoints merged into it.

{% hint style="danger" %}
**Each line creates or merges a UserPoint that has all the identifiers you list.** A merge migrates content onto a surviving UserPoint and archives the other - there is no unmerge. Validate the file before importing, especially when it comes from a join in your own systems.
{% endhint %}

{% hint style="info" %}
This import is only supported for datamarts using a UserPoint system version of `v201812` or later.
{% endhint %}

## How to

{% stepper %}
{% step %}

### Create the document import

Document type `USER_IDENTIFIERS_ASSOCIATION_DECLARATIONS`, mime type `APPLICATION_X_NDJSON`. Only `ndjson` is supported.

```bash
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports \
  -H 'Authorization: <YOUR_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
    "document_type": "USER_IDENTIFIERS_ASSOCIATION_DECLARATIONS",
    "mime_type": "APPLICATION_X_NDJSON",
    "encoding": "utf-8",
    "name": "<YOUR_DOCUMENT_IMPORT_NAME>"
}'
```

{% endstep %}

{% step %}

### Create an execution with one declaration per line

Each line holds an `identifiers` array - a list of identifier resources of any type.

```bash
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
  -H 'Authorization: <API_TOKEN>' \
  -H 'Content-Type: application/x-ndjson' \
  -d '
    {
      "identifiers":[
        { "type": "USER_EMAIL", "hash":"<EMAIL_HASH>" },
        { "type": "USER_AGENT", "user_agent_id": "<USER_AGENT_ID>" },
        { "type": "USER_ACCOUNT", "user_account_id": "<USER_ACCOUNT_ID>", "compartment_id": "<COMPARTMENT_ID>" }
      ]
    }
  '
```

{% endstep %}

{% step %}

### Read the result

Check `total_success`, `total_failure`, and the error file. Pay attention to `possible_issue_on_identifiers` and `top_identifiers` - an identifier appearing far more often than expected usually means a placeholder value slipped into the file. See [reading the result](/setup-and-monitor/collect-and-manage-your-data/import-data-in-batch.md#reading-the-result).
{% endstep %}
{% endstepper %}

{% hint style="success" %}
Different identifier types can be declared together on the same line. The data is `ndjson`, so declarations are separated by `\n`, not by commas.
{% endhint %}

## The identifier resources

An identifier resource takes one of three shapes, matching the three [identifier types](/setup-and-monitor/collect-and-manage-your-data/design-your-data-model-and-schema/user-identity/user-identifiers.md).

{% tabs %}
{% tab title="Email" %}

| Field        | Type             | Description                                                                  |
| ------------ | ---------------- | ---------------------------------------------------------------------------- |
| `type`       | `"USER_EMAIL"`   | The type of the identifier.                                                  |
| `hash`       | String           | A hash of the email. **The hashing function should be unique per datamart.** |
| `email`      | String, optional | The email address.                                                           |
| {% endtab %} |                  |                                                                              |

{% tab title="User agent" %}

| Field           | Type           | Description                 |
| --------------- | -------------- | --------------------------- |
| `type`          | `"USER_AGENT"` | The type of the identifier. |
| `user_agent_id` | String         | The user agent ID.          |
| {% endtab %}    |                |                             |

{% tab title="User account" %}

| Field             | Type             | Description                                                          |
| ----------------- | ---------------- | -------------------------------------------------------------------- |
| `type`            | `"USER_ACCOUNT"` | The type of the identifier.                                          |
| `user_account_id` | String           | The user account ID.                                                 |
| `compartment_id`  | String, optional | The compartment ID. **If omitted, the default compartment is used.** |
| {% endtab %}      |                  |                                                                      |
| {% endtabs %}     |                  |                                                                      |

## What happens per line

The outcome depends on what the platform already knows about the identifiers you list:

| Situation                                 | Result                                                                      |
| ----------------------------------------- | --------------------------------------------------------------------------- |
| One identifier matches an existing user   | The other identifiers are attached to that user.                            |
| Several identifiers match different users | Those users are **merged** into a single user carrying all the identifiers. |
| No identifier matches                     | A **new** user is created with all the identifiers attached.                |

## Verify

* The execution reports the expected success count.
* A test user that had two UserPoints now has one, carrying both identifier sets.
* The UserPoint total in [collection volumes](/setup-and-monitor/operate-and-monitor/monitor-collection-volume.md) drops by roughly the number of merges you expected - not by far more.
* No ordinary user becomes a [hyper point](/setup-and-monitor/collect-and-manage-your-data/design-your-data-model-and-schema/user-identity/userpoint-and-identity-graph.md#hyper-point).

## Related pages

<table data-view="cards" data-search="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Resolve identities</strong></td><td>The strategy behind these declarations.</td><td><a href="/setup-and-monitor/collect-and-manage-your-data/design-your-data-model-and-schema/user-identity/resolve-identities.md">Resolve identities</a></td></tr><tr><td><strong>Load identifiers</strong></td><td>The same job through the Data loader interface.</td><td><a href="/setup-and-monitor/collect-and-manage-your-data/import-data-in-batch/data-loader/load-identifiers.md">Load identifiers</a></td></tr><tr><td><strong>Import identifiers</strong></td><td>The opposite operation - deleting identifiers.</td><td><a href="/setup-and-monitor/collect-and-manage-your-data/import-data-in-batch/import-identifiers.md">Import identifiers</a></td></tr></tbody></table>


---

# 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.mediarithmics.io/setup-and-monitor/collect-and-manage-your-data/import-data-in-batch/enrich-users-with-identifiers.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.
