> For the complete documentation index, see [llms.txt](https://docs.userlane.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.userlane.com/developer-reference/push-user-attributes-via-api.md).

# Push user attributes via API

Send user attributes into Userlane from external systems using the Attribute Import API.

## About the Attribute Import API

The Attribute Import API sends user attributes into Userlane from other systems, in JSON format. Use it to push attributes such as role, department, region, or license type from a data warehouse, an internal service, or a scheduled job, so that Userlane reflects the attribute data already held elsewhere.

## Why use it

Use the API to:

* keep Userlane attributes current automatically, on a chosen schedule, instead of uploading spreadsheets by hand
* target content and filter analytics on attributes that live in other systems, not only those sent at login

See [Attributes](/administration/attributes.md) and [Audiences](/administration/audiences.md).

## What can be sent

A single request can carry two kinds of row, on their own or together:

* **Attribute definitions:** create or update the attributes themselves, meaning a name and a type.
* **User profile values:** set values for individual users, keyed by the customer's own public user ID.

A definition is only needed for an attribute that does not exist yet. Where the attribute already exists, skip the definitions and send the value under its key in the user's profile. Send a definition only when introducing a new attribute, or changing an existing one's name or type. Most ongoing updates carry user values alone.

## Company or property scope

There are two versions of the endpoint. They work identically and differ only in scope:

* **Company endpoint:** the attribute applies across the whole company. The company ID is a number.
* **Property endpoint:** the attribute belongs to a single application. In the API, a property is what the Userlane Portal calls an application, and the property ID is a short text ID visible in the URL path in the Portal.

An attribute sent to one scope never affects the other.

* [Company endpoint reference](https://dev.userlane.com/reference/bulkuploadcompanyattributes)
* [Property endpoint reference](https://dev.userlane.com/reference/bulkuploadpropertyattributes)

<div data-with-frame="true"><figure><img src="https://259567114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF6bxg8i3T6U4vZ3k7PHi%2Fuploads%2FYhd7Y3yZzX1EhhSK2Qfi%2Fimage.png?alt=media&#x26;token=991688ec-31c1-42e7-96b8-f11a3d414585" alt=""><figcaption><p>Company Endpoint</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="https://259567114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF6bxg8i3T6U4vZ3k7PHi%2Fuploads%2F2jZYyEHPC7X4951Zeq7N%2Fimage.png?alt=media&#x26;token=4fe2b143-e4a0-4d01-b3c1-3469056cd777" alt=""><figcaption><p>Company Endpoint</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="https://259567114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF6bxg8i3T6U4vZ3k7PHi%2Fuploads%2FQuvdizQtJcSEkv2w7yhz%2Fimage.png?alt=media&#x26;token=4e9ae422-2321-4c47-a302-99f351aa530b" alt=""><figcaption><p>Property Endpoint</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="https://259567114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF6bxg8i3T6U4vZ3k7PHi%2Fuploads%2FbLla6OwzWDsxPtAU14tI%2Fimage.png?alt=media&#x26;token=f86c2adc-efda-4c0c-bdc1-34eafc5f7566" alt=""><figcaption><p>Property Endpoint</p></figcaption></figure></div>

## How values are sent

Each value is wrapped in a small object with a `value` field. The value is never sent on its own. Sending the value without the `{ "value": ... }` wrapper is the most common reason a first request is rejected.

To set a value on an existing attribute, send only the user profile part, with the value under its key. To introduce a new attribute, add a definition object for it first, in the same request, then set its value for the user.

## Add new values, or replace existing ones

One setting, `idempotent`, controls what happens to a user's existing values:

* **`idempotent: false`, the default, adds.** The values sent are created or updated. Anything the user already has is left untouched. This is the safe everyday mode.
* **`idempotent: true` replaces.** The values sent are written, and any other values that user already has within the same scope are removed.

Leave `idempotent` out to add to what a user already has. Set it to `true` only where the request carries the complete, final set of values for the users it names, and clearing anything else is intended. `idempotent: true` affects only the users named in the request. Users not mentioned are never changed.

## How to push the data

### Generate the token

The API is protected and requires an authorization token. Generate the token in the Userlane Portal under **Settings > API Token**. See [Your Userlane API token](/developer-reference/your-userlane-api-token.md). The token is generated per Userlane Manager, and that Manager has to be a company admin.

### Test a request before automating

Each endpoint is available in the developer documentation, which includes a Try it button for sending a request directly from the browser. This is the fastest way to confirm that the token, the IDs, and the request body are correct before any code is written.

{% hint style="danger" %}
This is not a test sandbox. A request sent from Try it writes to the real users it names, using a real token. Always test against a user whose attribute values do not matter, so that a first attempt never touches real data.
{% endhint %}

To run a first request:

1. Open the company or property endpoint reference, linked above.
2. Paste the token into the **Authorization** field.
3. Enter the **company ID** or **property ID** in the path field.
4. In the request body, set one attribute and one value for the test user's ID.
5. Leave `idempotent` as `false`.
6. Click **Try it** to send the request.
7. Open that test user's profile in the Userlane Portal and confirm the value now appears.

Once a simple request works end to end, build the same call into the surrounding system and run it on a schedule.

### What each request needs

* **Company ID or property ID:** the scope being sent to, in the path.
* **Authorization token:** pasted into the Authorization field.
* **Attributes, user values, or both:** in the request body, with each value wrapped as `{ "value": ... }`.
* **`idempotent`,** optional: `false` to add, which is the default, or `true` to replace.

### Limits

A single request can carry up to 1,000 attribute definitions and up to 1,000 user records. The two limits are separate. To update more users than that, split them across several requests, for example 5,000 users as five requests of 1,000.

## Reading the result

<div align="left" data-with-frame="true"><figure><img src="https://259567114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF6bxg8i3T6U4vZ3k7PHi%2Fuploads%2FGGQK1ZBBCAdROJlunBHD%2Fimage.png?alt=media&#x26;token=9024a909-f006-4ed5-bed3-e48d259130c4" alt=""><figcaption></figcaption></figure></div>

Every request returns a summary of what happened: how many attributes were created or updated, how many user values were applied, and an `errors` list.

* An empty `errors` list means everything succeeded.
* Where some rows failed, each entry names the exact user and attribute that failed, and the reason, so only those need fixing and resending.

A response code of `207` means part of the request succeeded and part did not, so check the `errors` list. A `422` means the whole request was rejected and nothing was applied, so correct the request and resend.

## Good to know

Attributes are matched by their key. Sending a key that already exists updates it, and sending a new key creates a new attribute. To avoid duplicates, keep keys consistent, for example always `job_title` rather than sometimes `jobTitle`.

## Troubleshooting

A failed request returns an error in the result section. Most issues relate to:

* a token whose Manager is not a company admin, returning `403`
* an invalid or expired token, returning `401`
* a request body that did not validate, usually a value missing the `{ "value": ... }` wrapper, returning `422`
* values disappearing, which means the request was sent with `idempotent: true`

Review the parameters against this article. If the issue persists, contact Userlane.

## Relevant articles

{% content-ref url="/pages/TcXdqgybeGLnS1EODhcN" %}
[Your Userlane API token](/developer-reference/your-userlane-api-token.md)
{% endcontent-ref %}

{% content-ref url="/pages/0XiPZYLLfKewriq8G6Av" %}
[User profile data export](/developer-reference/user-profile-data-export.md)
{% endcontent-ref %}

{% content-ref url="/pages/gtcOzAVjL7zzv75As2Jd" %}
[Attributes](/administration/attributes.md)
{% endcontent-ref %}

{% content-ref url="/pages/heUmxS6HxlGKqCQSjqbs" %}
[Attribute sources](/administration/attributes/attribute-sources.md)
{% endcontent-ref %}

{% content-ref url="/pages/TKBRGmMaapWk0xuF3XwG" %}
[Audiences](/administration/audiences.md)
{% endcontent-ref %}


---

# 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.userlane.com/developer-reference/push-user-attributes-via-api.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.
