> ## 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.

# Events Bulk Import

> The Import API allows you to import historical user data from other platforms into Userpilot. With this API, you can migrate data related to user and company.

The Import API allows you to import historical user data from other platforms into Userpilot. With this API, you can migrate data related to user and company identification, page views, and custom events. This enables a seamless transition and continuity of insights, providing a comprehensive view of user interactions.

<Note>
  This feature is available on the Enterprise plan only or as an add-on to the
  Growth plan. If interested in adding this feature please contact
  [support@userpilot.com](mailto:support@userpilot.com).
</Note>

## Use Cases

1. **Data Migration:** Migrate historical data from other analytics platforms to Userpilot, ensuring no loss of valuable insights.
2. **Retrospective Analysis:** Analyze historical user behavior and feature engagement by importing past data on user actions, page views, and events.

<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>

<Tip>
  If you're migrating from another provider, complete the import process
  **before** installing the SDK. This ensures historical data is ready for
  analysis once Userpilot starts tracking live events.
</Tip>

***

## Authorization

See the [Authentication](../authentication) and [Environment](../environment) pages for details on API key usage and endpoint URLs.

**Authentication Method:**

Include your API key in the `Authorization` header:

```http theme={null}
Authorization: Token {{API_KEY}}
```

<Note>All API requests must be made over HTTPS.</Note>

<Warning>
  Your API key carries many privileges, so be sure to keep it secure! Do not
  share your secret API keys in publicly accessible areas.
</Warning>

***

## Rate Limits

The Import API implements rate limiting to maintain system stability and ensure fair resource allocation across all users. These limits help prevent system overload while allowing efficient data migration workflows.

### Rate Limit Details

* **Job Limitation**: **One import job at a time** per application token
* **File Size**: **Up to 1 GB** file size for import operations

### Error Responses

The API returns specific error codes when limits are exceeded:

* **`409 Conflict`**: Returned when attempting to create a new import job while another is in progress
* **`413 Payload Too Large`**: Returned when file size exceeds 1 GB

### Best Practices

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

  **Implement Retry Logic**: When encountering a 409 Conflict error, wait for the current job to complete before retrying.

  **Monitor Job Progress**: Use the job status endpoints to track import progress and avoid conflicts.

  **Optimize File Sizes**: For very large datasets, consider splitting files to stay within the 1 GB limit.
</Tip>

***

## Endpoints

For most users, the HTTP API endpoint URL is `https://analytex.userpilot.io`. If you are on Enterprise or EU hosting, refer to the [Environment](../environment) page in the application to retrieve your dedicated endpoint.

### 1. Request Data Import

#### Endpoint

```http theme={null}
POST {{ENDPOINT}}/v1/imports
```

<EnvironmentNote />

#### Description

Initiates a data import job. Accepts a file in **CSV** or **NDJSON** format containing historical data.

#### Headers

| Header          | Value                 | Required |
| --------------- | --------------------- | -------- |
| `Content-Type`  | `multipart/form-data` | Yes      |
| `Authorization` | `Token {{API_KEY}}`   | Yes      |

#### Request Parameters

| Parameter | Type | Required | Description                                                                                       |
| --------- | ---- | -------- | ------------------------------------------------------------------------------------------------- |
| file      | File | Yes      | The CSV or NDJSON file containing the data to be imported. See the event schema for more details. |

#### Data Format

The imported data should conform to a list of events. See the [Import API Event Schema](./event-schema.mdx) for details on supported event types and required fields.

#### Example Import File

<Tabs>
  <Tab title="NDJSON">
    ```json file.ndjson theme={null}
    {"event_type": "identify_user", "user_id": "user_123", "inserted_at": "2024-07-28T08:55:35.874555", "metadata": { "name": "John Doe", "email": "john.doe@example.com", "location": "Dublin, Ireland" },"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"}
    {"event_type": "identify_company","company_id": "company_123","inserted_at": "2024-07-28T08:55:35.874555","metadata": {"name": "Acme Labs Inc.","industry": "Software","size": "200-500","location": "San Francisco, CA"}}
    ```
  </Tab>

  <Tab title="CSV">
    ```csv file.csv theme={null}
    event_type,event_name,source,user_id,company_id,hostname,pathname,country_code,screen_width,screen_height,operating_system,browser,browser_language,user_agent,device_type,inserted_at,metadata
    identify_user,,web-client,User-7320-001,Company-607-001,campfire-example.userpilot.io,/profile/settings/,DE,1086,696,Mac,Edge,de-DE,Edge - Mozilla/5.0 (Mac) AppleWebKit/537.36,Mobile,2023-12-26 14:36:15.453703,"{""created_at"": ""1694172975"", ""name"": ""User-Alice"", ""prop_0"": ""value_743"", ""prop_1"": ""value_927""}"
    page_view,,web-client,User-9491-002,Company-973-002,campfire-example.userpilot.io,/home/,DE,832,809,iOS,Chrome,fr-FR,Chrome - Mozilla/5.0 (iOS) AppleWebKit/537.36,Mobile,2024-04-13 14:36:15.453788,"{}"
    track,created_project,web-client,User-6267-003,Company-584-003,campfire-example.userpilot.io,/profile/settings/,PS,1114,704,iOS,Safari,en-US,Safari - Mozilla/5.0 (iOS) AppleWebKit/537.36,Mobile,2024-05-05 14:36:15.453813,"{""created_at"": ""1730810175"", ""name"": ""User-Bob"", ""prop_0"": ""value_17""}"
    ```
  </Tab>
</Tabs>

**Uploading the File**

```bash theme={null}
curl -X POST "{{ENDPOINT}}/v1/imports" \
-H "Authorization: Token {{API_KEY}}" \
-F "file=@/path/to/import_data.ndjson"
```

#### Response

<Tabs>
  <Tab title="Success">
    ```json theme={null}
    {
      "end_time": null,
      "file_size": 2234,
      "filename": "2024-10-28.ndjson",
      "job_id": "imports:jobs:NX-51f4acf7:f681073b-21ac-4276-9af5-c662dc05fb25",
      "links": "/v1/background_jobs/imports:jobs:NX-51f4acf7:f681073b-21ac-4276-9af5-c662dc05fb25",
      "start_time": "2024-11-28T10:34:11.376662",
      "status": "queued",
      "total_rows": 0
    }
    ```
  </Tab>

  <Tab title="Error">
    ```json theme={null}
    {
      "errors": [
        {
          "details": "There is already an export job in progress, you can only have one export job in progress at a time.",
          "error": "Conflict",
          "error_code": "409",
          "message": "The request could not be completed due to a conflict with the current state of the target resource."
        }
      ]
    }
    ```
  </Tab>
</Tabs>

***

### 2. Get All Import Job Statuses

#### Endpoint

```http theme={null}
GET {{ENDPOINT}}/v1/background_jobs
```

#### Description

Fetches the status of all import jobs, allowing users to monitor the progress of multiple imports at once.

#### Headers

| Header          | Value               | Required |
| --------------- | ------------------- | -------- |
| `Authorization` | `Token {{API_KEY}}` | Yes      |

#### Example Request

```bash theme={null}
curl -X GET "{{ENDPOINT}}/v1/background_jobs" \
-H "Authorization: Token {{API_KEY}}"
```

#### Response

Returns a list of job objects, each with details such as job\_id, status, start\_time, end\_time, total\_rows, and reason\_for\_failure (if any).

```json theme={null}
[
  {
    "elapsed_time": 6,
    "end_time": "2025-05-19T07:23:00.354452",
    "file_size": 757,
    "filename": "2024-10-28.ndjson",
    "job_id": "imports:jobs:NX-ac54070e:c6f91301-54c1-4df7-a077-b34715c38875",
    "links": "/v1/background_jobs/imports:jobs:NX-ac54070e:c6f91301-54c1-4df7-a077-b34715c38875",
    "start_time": "2025-05-19T07:22:54.409499",
    "status": "completed",
    "total_rows": 3
  },
  {
    "elapsed_time": 0,
    "end_time": "2025-05-19T07:09:49.883288",
    "file_size": 416,
    "filename": "2024-10-28.ndjson",
    "job_id": "imports:jobs:NX-ac54070e:1fd8f0d4-cd97-432f-86fe-3df9effc1912",
    "links": "/v1/background_jobs/imports:jobs:NX-ac54070e:1fd8f0d4-cd97-432f-86fe-3df9effc1912",
    "reason_for_failure": [
      "Required field `user_id` not provided in the row: %{\"event_name\" => \"\", \"event_type\" => \"identify_user\", \"metadata\" => %{\"avg_resolution_time\" => \"2h\", \"customer_satisfaction\" => \"4.8\", \"escalation_count\" => \"1\", \"last_ticket_created\" => \"2025-02-01T10:20:30Z\", \"tickets_created\" => \"15\", \"tickets_pending\" => \"1\", \"tickets_resolved\" => \"14\"}}"
    ],
    "start_time": "2025-05-19T07:09:49.880967",
    "status": "failed",
    "total_rows": 0
  }
  //... more jobs
]
```

***

### 3. Get Job Status by ID

#### Endpoint

```http theme={null}
GET {{ENDPOINT}}/api/background_jobs/:job_id
```

#### Description

Fetches the status of a specific import job using its `job_id`, useful for tracking a single import job.

#### Headers

| Header          | Value               | Required |
| --------------- | ------------------- | -------- |
| `Authorization` | `Token {{API_KEY}}` | Yes      |

#### Path Parameters

| Parameter | Type   | Required | Description                             |
| --------- | ------ | -------- | --------------------------------------- |
| job\_id   | String | Yes      | The unique identifier of the import job |

#### Example Request

```bash theme={null}
curl -X GET "{{ENDPOINT}}/api/background_jobs/:job_id" \
-H "Authorization: Token {{API_KEY}}"
```

#### Response

Returns job details including job\_id, status, start\_time, end\_time, total\_rows, and reason\_for\_failure (if any).

```json theme={null}
{
  "elapsed_time": 6,
  "end_time": "2025-05-19T07:23:00.354452",
  "file_size": 757,
  "filename": "2024-10-28.ndjson",
  "job_id": "imports:jobs:NX-ac54070e:c6f91301-54c1-4df7-a077-b34715c38875",
  "links": "/v1/background_jobs/imports:jobs:NX-ac54070e:c6f91301-54c1-4df7-a077-b34715c38875",
  "start_time": "2025-05-19T07:22:54.409499",
  "status": "completed",
  "total_rows": 3
}
```

***

<Note>
  For required validation rules for your import file, see the [Row Validation
  Rules](./row-validation.mdx) page.
</Note>

<Tip>
  For best practices on importing user and company data, see [Best Practices for
  Accumulative Properties](./best-practices.mdx).
</Tip>

If you have any questions or encounter any issues, please don't hesitate to reach out to our support team. We're here to help!

📧 **Contact Support**: [support@userpilot.com](mailto:support@userpilot.com)
