> ## Documentation Index
> Fetch the complete documentation index at: https://docs.userpilot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk Identify/Update Users

> Bulk identify and update user profiles using Userpilot's HTTP API for large-scale user data synchronization.

The Bulk Identify Users API allows you to create or update multiple user profiles in a single request. This is ideal for large-scale data synchronization, initial user imports, or batch updates from your CRM or database systems.

<Warning>
  **PII Data Notice**

  Before passing any Personally Identifiable Information (PII) such as names, emails, or other sensitive user data to Userpilot:

  * **Security & Compliance:** Verify internally with your legal, security, and compliance teams that doing so aligns with your organization's data privacy policies and applicable regulations (e.g., GDPR, CCPA).

  * **Data Type Mapping:** Ensure correct data type mapping for all properties. Userpilot supports String, Numeric, and Date types. Make sure dates are in ISO8601 format and numeric values are properly formatted. Incorrect type mapping can cause issues with segmentation, analytics, and debugging.

  * **Debugging:** Proper data formatting is crucial for effective debugging and troubleshooting. Verify that your data maps correctly to Userpilot's expected formats before implementation.
</Warning>

## Endpoint

```http theme={null}
[POST] https://analytex.userpilot.io/v1/users/bulk_identify
```

<Note>
  The endpoint URL uses the `analytex` environment. For EU data residency, use
  `analytex-eu` instead. See [Environment
  Settings](https://run.userpilot.io/environment) for your specific endpoint.
</Note>

{" "}

## Headers

| Header          | Value                               | Required |
| --------------- | ----------------------------------- | -------- |
| `Content-Type`  | `application/json`                  | Yes      |
| `Accept`        | `application/json, text/plain, */*` | Yes      |
| `Authorization` | `Token {YOUR_API_KEY}`              | Yes      |

## Request Body

| Field        | Type   | Required | Description                                           |
| ------------ | ------ | -------- | ----------------------------------------------------- |
| `users`      | array  | Yes      | Array of user objects                                 |
| `user_id`    | string | Yes      | Unique identifier for the user                        |
| `company_id` | string | No       | Unique identifier for the company (if applicable)     |
| `metadata`   | object | No       | Key-value pairs describing the user (primitives only) |

## JSON Payload Example

```json theme={null}
{
  "users": [
    {
      "user_id": "user_001",
      "company_id": "comp001",
      "metadata": {
        "last_ticket_created": "2025-02-01T10:20:30Z",
        "tickets_created": "15",
        "tickets_resolved": "14",
        "tickets_pending": "1",
        "avg_resolution_time": "2h",
        "customer_satisfaction": "4.8",
        "escalation_count": "1"
      }
    },
    {
      "user_id": "user_002",
      "company_id": "comp002",
      "metadata": {
        "last_ticket_created": "2025-01-31T09:15:00Z",
        "tickets_created": "8",
        "tickets_resolved": "7",
        "tickets_pending": "1",
        "avg_resolution_time": "3h",
        "customer_satisfaction": "4.5",
        "escalation_count": "0"
      }
    }
    // ... Additional users up to 10,000 total
  ]
}
```

<Tip>
  **Optimize Your Payload**: Use the full 10,000 record limit to maximize processing efficiency. The example above shows the structure for individual records - you can include up to 10,000 such records in a single request.
</Tip>

## Response

A successful call returns a job object:

```json theme={null}
{
  "job_id": "9536d797-7039-4d30-8c11-ac437367d732",
  "status": "queued",
  "submitted_at": "2025-02-02T12:34:56Z"
}
```

<Tip>
  **Monitor Your Job**: Use the job ID from the response to track the status of your bulk update job. Remember that only one bulk update job (user or company) can run at a time.
</Tip>

***

## File Upload (NDJSON)

For very large updates, you may upload NDJSON files containing user profiles.

### Endpoint

```http theme={null}
[POST] https://analytex.userpilot.io/v1/users/bulk_identify
```

<Note>
  The endpoint URL uses the `analytex` environment. For EU data residency, use
  `analytex-eu` instead. See [Environment
  Settings](https://run.userpilot.io/environment) for your specific endpoint.
</Note>

{" "}

### Headers

| Header          | Value                               | Required |
| --------------- | ----------------------------------- | -------- |
| `Content-Type`  | `multipart/form-data`               | Yes      |
| `Accept`        | `application/json, text/plain, */*` | Yes      |
| `Authorization` | `Token {YOUR_API_KEY}`              | Yes      |

### Request Body

Submit the file using multipart/form-data. Include a key called `file` with your NDJSON file:

```bash theme={null}
curl -X POST "https://analytex.userpilot.io/v1/users/bulk_identify" \
     -H "Authorization: Token {YOUR_API_KEY}" \
     -H "Content-Type: multipart/form-data" \
     -F "file=@/path/to/your/file.ndjson"
```

<Tip>
  Each line in the file should be a valid JSON object.
</Tip>

<Warning>
  File size is limited to 50 MB. Each request can contain up to 10,000 users.
</Warning>

***

## Rate Limits

The Bulk Updates API implements rate limiting to ensure efficient processing of large-scale user data operations while maintaining system stability. These limits help optimize performance for bulk user profile updates and synchronizations.

### Rate Limit Details

* **Job Limitation**: **One job at a time** - The system processes only one bulk update job at a time (either user or company operations)
* **User Processing**: **1,800 users per minute** service consumption rate
* **JSON Payload**: **Up to 10,000 records per request**
* **File Upload**: **Up to 50 MB file size**

### Error Responses

When you exceed these limits, the API returns:

* **`409 Conflict`**: Returned when attempting to create a new job while another is in progress
* **`413 Payload Too Large`**: Returned when file size exceeds 50 MB or payload exceeds 10,000 records

### Best Practices

<Tip>
  **Check Job Status**: Always verify no existing bulk update jobs are running before initiating a new one.

  **Optimize Batch Sizes**: Use the full 10,000 record limit for JSON payloads to maximize efficiency.

  **Monitor Processing**: Track your user processing speed to stay within the 1,800 users per minute limit.

  **Handle File Uploads**: For large datasets, use file uploads (up to 50 MB) instead of JSON payloads.
</Tip>

***

## Limitations

* File size up to 50 MB (for file uploads).
* JSON/NDJSON list up to 10,000 users per request.
* Only primitive types (string, number, boolean, null) are supported in metadata.

***

## Best Practices

* **Validate Your Data:** Ensure each record includes the required identifiers (`user_id`) and that metadata is formatted correctly.
* **Monitor Jobs:** Always use the job monitoring endpoints to check the status of your bulk updates.
* **Rate Limits and Retries:** If you experience rate limits or timeouts, batch your requests and monitor job statuses before submitting more.

***

## Troubleshooting

* **Authentication Errors:** Verify your API token and that it is sent in the `Authorization` header.
* **Invalid Payload:** Ensure your JSON/NDJSON is well-formed and required fields are present.
* **Job Failures:** Use the job status endpoint to inspect error messages for failed records or processing issues.
