> You are reading the Docusign Developer Documentation. For clean Markdown of any page, append .md to the page URL.
>
> Documentation indexes by section:
> - APIs and SDKs: https://docusign.docs.buildwithfern.com/docs/llms.txt
> - Platform 101: https://docusign.docs.buildwithfern.com/platform/llms.txt
> - Extension Apps: https://docusign.docs.buildwithfern.com/extension-apps/llms.txt
> - Docusign CLI: https://docusign.docs.buildwithfern.com/docusign-cli/llms.txt
>
> Authentication (OAuth, JWT Grant, M2M): https://docusign.docs.buildwithfern.com/platform/auth
> Webhooks and Connect: https://docusign.docs.buildwithfern.com/platform/webhooks
>
> OpenAPI specifications: https://docusign.docs.buildwithfern.com/openapi.json
> MCP server: https://docusign.docs.buildwithfern.com/_mcp/server

# How to bulk export user data

> Learn how to use the Docusign Admin API to export a list of account users to edit.

This topic demonstrates how to bulk export user accounts within an organization into a CSV (comma separated value) file.

> **Note**
>
> Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects: [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).

## Required data

Running the code in this how-to requires this data:

| Data element       | Description                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \{ACCOUNT_ID}      | A [GUID](http://guid.one/) value that identifies the account to which the user will be added. To determine your account IDs, open your [Organization](https://apps-d.docusign.com/admin/organization/) home page in Docusign Admin, then select the **Accounts** tile. The **Account ID** values for each account in your organization will be shown on the resulting page. |
| Admin access       | The caller must be at least one of the following:- A full organization administrator
- A delegated organization administratorSee [Organization Administrators](https://support.docusign.com/s/document-item?language=en_US\&rsc_301\&bundleId=rrf1583359212854\&topicId=god1583359152535.html&_LANG=enus) for details on Docusign Admin roles.                              |
| \{BASE_PATH}       | A string value that forms the root of the URL required to make API calls. The base path value in the example code is set to target the developer environment at https\://\<domain>/management Where \<domain> is api-d.docusign.net for the developer environment and api.docusign.net for production.                                                                      |
| \{ORGANIZATION_ID} | A [GUID](http://guid.one/) value that identifies the the organization that contains the account to which the user will be added. Copy the value from the **Organization ID** field in the **Organization** section of the [Account Profile](https://admindemo.docusign.com/authenticate?goTo=accountProfile) page.                                                          |

## Step 1. Obtain your OAuth token

To make the API calls shown in this how-to, you need a valid OAuth access token. Docusign supports access tokens for three different recommended OAuth grant types: Public Authorization Code Grant, Confidential Authorization Code Grant, and JSON Web Token (JWT) Grant. Choose the OAuth grant type appropriate for your scenario.

Docusign Admin OAuth access tokens are the same ones used for our [eSignature REST API](/docs/esign-rest-api/esign101/auth), although you must request one or more Docusign Admin scopes to call the Docusign Admin API. The endpoint calls made in this how-to require that you request the Docusign Admin-specific `user_write` scope when obtaining your access token.

> **Note**
>
> See [Docusign Admin Authentication](/docs/admin-api/admin101/auth) for details and the full list of Docusign Admin scopes.

![Three icons that represent the three methods a user can use to obtain an OAuth token: JSON Web Token (JWT), Public Authorization Code Grant (ACG), and Confidential Authorization Code grant](/_fern-files/_img/64f473773042ee439449a096bf7673292b1585b86a4ccc55f82ba0dda41f61a1.webp)

## Step 2. Construct your API headers

After you have a valid OAuth access token, you are ready to construct the API headers that you will pass to the API call. Construct your headers like this, but make sure to substitute your valid OAuth access token for \{ACCESS_TOKEN}.

**`Bash`**

```bash title="Bash"
declare -a Headers=('--header' "Authorization: Bearer ${ACCESS_TOKEN}"
    '--header' "Accept: application/json"
    '--header' "Content-Type: application/json")
```

**`C#`**

```csharp title="C#"
var apiClient = new DocuSignClient(basePath);
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
```

**`Java`**

```java title="Java"
ApiClient apiClient = new ApiClient(basePath);
apiClient.addDefaultHeader(
        HttpHeaders.AUTHORIZATION,
        BEARER_AUTHENTICATION + accessToken);
```

**`Node.js`**

```javascript title="Node.js"
const apiClient = new docusignAdmin.ApiClient();
apiClient.setBasePath(args.basePath);
apiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
```

**`PHP`**

```php title="PHP"
$config = new Configuration();
$config->setAccessToken($accessToken);
$config->setHost('https://api-d.docusign.net/management');
$config->addDefaultHeader('Authorization', 'Bearer ' . $accessToken);
$this->apiClient = new ApiClient($config);
```

**`PowerShell`**

```text title="PowerShell"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.add("Authorization", "Bearer $accessToken")
$headers.add("Content-Type", "application/json")
```

**`Python`**

```python title="Python"
api_client = create_admin_api_client(
    access_token=session["ds_access_token"]
)

# Create the export API object
export_api = BulkExportsApi(api_client=api_client)
```

**`Ruby`**

```ruby title="Ruby"
configuration = DocuSign_Admin::Configuration.new
configuration.host = Rails.configuration.admin_host

api_client = DocuSign_Admin::ApiClient.new(configuration)
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
```

## Step 3. Create the bulk export request

Next, begin the process of creating the bulk export list by calling the [createUserListExport](/docs/admin-api/reference/bulkoperations/userexport/createuserlistexport) endpoint. You can retrieve the resulting CSV data in a future step.

Creating and provisioning the bulk export list can take some time, especially for large organizations spread out over several regions. You can check the status of your bulk export request by calling the [getUserListExport](/docs/admin-api/reference/bulkoperations/userexport/getuserlistexport) endpoint, as demonstrated in the next step.

You can filter the users that will be added to the generated bulk export user list using the type parameter of the request body, which specifies the category of users within your organization that will be added to the generated list of user data. Possible values are:

* `organization_external_memberships_export`: Returns a list of users with email addresses that are part of your organization’s domain(s), but with memberships in accounts that are not part of your organization.
* `organization_memberships_export`: Returns a list of all users with memberships in your organization’s accounts.
* `organization_domain_users_export`: Returns a list of all users within your organization’s domain(s).

**`Bash`**

```bash title="Bash"
retryCount=0
downloadUrl=''
while [ $retryCount -le 5 ]; do
    echo ''
    echo 'Retrieving Bulk Action Status...'
    echo ''
    curl --request GET ${base_path}/v2/organizations/${ORGANIZATION_ID}/exports/user_list/${requestId} \
        "${Headers[@]}" \
        --output ${response}

    echo ''
    echo "Response:"
    echo ''
    cat $response
    echo ''

    #Check the status of the Bulk Action
    status=$(cat $response | grep status | sed 's/.*\"status\":\"//' | sed 's/\",.*//')
    echo "Status: $status"

    if [ "$status" = "completed" ]; then
        echo ''
        echo 'Bulk Request has been completed'
        echo ''
        downloadUrl=$(cat $response | grep url | sed 's/.*\"url\":\"//' | sed 's/\",.*//')
        echo "Download Url: $downloadUrl"
        let retryCount=6
    else
        echo ''
        echo 'Bulk Request has not been completed. Retrying in 5 seconds'
        echo ''
        sleep 5
        let retryCount=retryCount+1
    fi
done
```

**`C#`**

```csharp title="C#"
var bulkExportsApi = new BulkExportsApi(apiClient);

var organizationExportRequest = new OrganizationExportRequest
{
    Type = "organization_memberships_export",
};

var exportResponse = bulkExportsApi.CreateUserListExportWithHttpInfo(organizationId, organizationExportRequest);
exportResponse.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
exportResponse.Headers.TryGetValue("X-RateLimit-Reset", out string reset);

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}
```

**`Java`**

```java title="Java"
BulkExportsApi bulkExportsApi = createBulkExportsApi(this.user.getAccessToken(), this.session.getBasePath());

OrganizationExportResponse bulkList = BulkExportUserDataService.createUserListExport(
        bulkExportsApi,
        this.getOrganizationId(this.user.getAccessToken(), this.session.getBasePath()));
```

**`Node.js`**

```javascript title="Node.js"
const bulkExportsApi = new docusignAdmin.BulkExportsApi(apiClient);
let exportResponse = await bulkExportsApi.createUserListExport(requestBody, args.organizationId, (error, data, response) => {
    const headers = response?.headers;

    const remaining = headers?.['x-ratelimit-remaining'];
    const reset = headers?.['x-ratelimit-reset'];

    if (remaining && reset) {
      const resetInstant = new Date(Number(reset) * 1000);

      console.log(`API calls remaining: ${remaining}`);
      console.log(`Next Reset: ${resetInstant.toISOString()}`);
    }
});
```

**`PHP`**

```php title="PHP"
$bulkExportsApi = $clientService->bulkExportsAPI();
$request = new OrganizationExportResponse();
$request->setType("organization_memberships_export");
$bulkList = $bulkExportsApi->createUserListExportWithHttpInfo($organizationId, $request);
```

**`PowerShell`**

```text title="PowerShell"
Write-Output "Checking Bulk Action Status"
$uri2 = "${base_path}/v2/organizations/$organizationId/exports/user_list/$requestId"
$result2 = Invoke-WebRequest -headers $headers -Uri $uri2 -Method GET
$result2.Content
$results = $result2 | ConvertFrom-Json
$retrycount = 0

Do {
    Write-Output "The Bulk Action has not been completed. Retrying in 5 seconds. To abort, Press Control+C"
    Start-Sleep 5
    $result2 = Invoke-WebRequest -headers $headers -Uri $uri2 -Method GET
    $resultStatus = $($result2 | ConvertFrom-Json).status
    $retrycount++
    if ($retrycount -eq 5) {
        exit 1
    }
} While ($resultStatus -ne "completed")

if ($resultStatus -eq "completed") {
    Write-Output $($result2 | ConvertFrom-Json).results.id
    $resultId = $($result2 | ConvertFrom-Json).results.id
}
else {
    Write-Output "An error has occurred, the Bulk Action has not been completed."
    exit 1
}
```

**`Python`**

```python title="Python"
(response, status, headers) = export_api.create_user_list_export_with_http_info(
    organization_id,
    {
        "type": "organization_memberships_export"
    }
)

remaining = headers.get("X-RateLimit-Remaining")
reset = headers.get("X-RateLimit-Reset")

if remaining is not None and reset is not None:
    reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
    print(f"API calls remaining: {remaining}")
    print(f"Next Reset: {reset_date}")
```

**`Ruby`**

```ruby title="Ruby"
@bulk_exports_api = DocuSign_Admin::BulkExportsApi.new(api_client)
response, _status, headers = bulk_exports_api.create_user_list_export_with_http_info(args[:organization_id], args[:request_body])

remaining = headers['X-RateLimit-Remaining']
reset = headers['X-RateLimit-Reset']

if remaining && reset
  reset_date = Time.at(reset.to_i).utc
  puts "API calls remaining: #{remaining}"
  puts "Next Reset: #{reset_date}"
end
```

## Expected response

After a successful request, you will receive a response similar to this.

The important parts of the response are highlighted below:

| Property       | Description                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | Identifies the request. You can use this value to check the status of the export request again, if its status is not yet `completed`.                                                                                                                                                                                                                                                                           |
| `status`       | The status of the request. If the bulk export data is still being created, this value will be `queued` or `in_progress`. When the bulk export data is ready, this value will be `completed`. Possible values are:- `unknown:` Unknown status.
- `queued:` Ready to be created.
- `in_process:` The export is being created.
- `completed:` The export was created.
- `failed:` The export could not be created. |
| `metadata_url` | The endpoint URL that you can call to check the request status and, if it is completed, get a download link for the export data.                                                                                                                                                                                                                                                                                |

If you receive a **401 - Unauthorized** response, your access token is not valid for the endpoint. If you receive this error:

* Make sure that your access token has the `user_read` scope.
* Make sure that the calling user has admin rights.

**`Sample response`**

```json title="Sample response"
{
  "id": "f7638356-xxxx-xxxx-xxxx-4935e87d88c1",
  "type": "organization_memberships_export",
  "requestor": {
    "name": "1007 a",
    "id": "9cb13e29-xxxx-xxxx-xxxx-6baeba17505c",
    "type": "user",
    "email": "1007a@example.com"
  },
  "created": "2021-10-07T22:16:16.4923965Z",
  "last_modified": "2021-10-07T22:16:16.4923965Z",
  "status": "queued",
  "metadata_url": "https://api-d.docusign.net/management/v2/organizations/e1b55b52-xxxx-xxxx-xxxx-8a7ff52dd8e0/exports/user_list/f7638356-xxxx-xxxx-xxxx-4935e87d88c1",
  "percent_completed": 0,
  "number_rows": 0,
  "size_bytes": 0
}
```

## Step 4. Check the request status

It can take some time for a bulk user export request to be fully created, depending on the number of users that it contains and the regions it encompasses. You can call the [getUserListExport](/docs/admin-api/reference/bulkoperations/userexport/getuserlistexport) endpoint to check the status of your pending request and, if complete, obtain a URL that you can call to download the CSV file containing the export data.

**Important**: Be sure to replace the `requestId` value in the request with the ID of the bulk user export request that you created in the previous step.

**`Bash`**

```bash title="Bash"
curl --request GET ${base_path}/v2/organizations/${ORGANIZATION_ID}/exports/user_list/${requestId} \
    "${Headers[@]}" \
    --output ${response}
```

**`C#`**

```csharp title="C#"
int retryCount = 5;

while (retryCount >= 0)
{
    if (exportResponse.Data.Results != null)
    {
        GetUserData(accessToken, exportResponse.Data.Results.FirstOrDefault().Url, filePath);
        break;
    }
    else
    {
        --retryCount;
        System.Threading.Thread.Sleep(5000);
        exportResponse = bulkExportsApi.GetUserListExportWithHttpInfo(organizationId, exportResponse.Data.Id);
        exportResponse.Headers.TryGetValue("X-RateLimit-Remaining", out remaining);
        exportResponse.Headers.TryGetValue("X-RateLimit-Reset", out reset);

        if (reset != null && remaining != null)
        {
            DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
            Console.WriteLine("API calls remaining: " + remaining);
            Console.WriteLine("Next Reset: " + resetDate);
        }
    }
}
```

**`Java`**

```java title="Java"
OrganizationExportResponse data = BulkExportUserDataService.bulkExportUserData(
        bulkExportsApi,
        this.getOrganizationId(this.user.getAccessToken(), this.session.getBasePath()),
        bulkList.getId());
```

**`Node.js`**

```javascript title="Node.js"
const bulkExportResponse = await bulkExportsApi.getUserListExport(args.organizationId, exportId, (error, data, response) => {
  const headers = response?.headers;

  const remaining = headers?.['x-ratelimit-remaining'];
  const reset = headers?.['x-ratelimit-reset'];

  if (remaining && reset) {
    const resetInstant = new Date(Number(reset) * 1000);

    console.log(`API calls remaining: ${remaining}`);
    console.log(`Next Reset: ${resetInstant.toISOString()}`);
  }
  });
```

**`PHP`**

```php title="PHP"
$organizationExportResponse = $bulkExportsApi->getUserListExportWithHttpInfo($organizationId, $bulkList[0]["id"]);
```

**`PowerShell`**

```text title="PowerShell"
$uri2 = "${base_path}/v2/organizations/$organizationId/exports/user_list/$requestId"
$result2 = Invoke-WebRequest -headers $headers -Uri $uri2 -Method GET
$result2.Content
$results = $result2 | ConvertFrom-Json
```

**`Python`**

```python title="Python"
(response, status, headers) = export_api.get_user_list_export_with_http_info(
    organization_id,
    session['user_list_export_id']
)

remaining = headers.get("X-RateLimit-Remaining")
reset = headers.get("X-RateLimit-Reset")

if remaining is not None and reset is not None:
    reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
    print(f"API calls remaining: {remaining}")
    print(f"Next Reset: {reset_date}")
```

**`Ruby`**

```ruby title="Ruby"
retry_count = 5
while retry_count >= 0
  if response.results
    get_exported_user_data(args, response.id)
    break
  else
    retry_count -= 1
    sleep(5)
    response, _status, headers = bulk_exports_api.get_user_list_export_with_http_info(args[:organization_id], response.id)

    remaining = headers['X-RateLimit-Remaining']
    reset = headers['X-RateLimit-Reset']

    if remaining && reset
      reset_date = Time.at(reset.to_i).utc
      puts "API calls remaining: #{remaining}"
      puts "Next Reset: #{reset_date}"
    end
  end
end
```

## Expected response

This call will return a response similar to this.

The important parts of the response are highlighted below:

| Property            | Description                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                | Identifies the request. You can use this value to check the status of the export request again, if its status is not yet `completed`.                                                                                                                                                                                                                                                                           |
| `status`            | The status of the request. If the bulk export data is still being created, this value will be `queued` or `in_progress`. When the bulk export data is ready, this value will be `completed`. Possible values are:- `unknown:` Unknown status.
- `queued:` Ready to be created.
- `in_process:` The export is being created.
- `completed:` The export was created.
- `failed:` The export could not be created. |
| `success`           | Indicates whether the export was successful. If false, the export failed and the data cannot be downloaded.                                                                                                                                                                                                                                                                                                     |
| `percent_completed` | Indicates how close to completion the export request is.                                                                                                                                                                                                                                                                                                                                                        |
| `results.id`        | The ID of the generated user list data.                                                                                                                                                                                                                                                                                                                                                                         |
| `results.url`       | The URL that you can call to download the exported list of user data, as demonstrated in the next step.                                                                                                                                                                                                                                                                                                         |

**`Sample response`**

```json title="Sample response"
{
  "id": "f7638356-xxxx-xxxx-xxxx-4935e87d88c1",
  "type": "organization_memberships_export",
  "requestor": {
    "name": "1007 a",
    "id": "9cb13e29-xxxx-xxxx-xxxx-6baeba17505c",
    "type": "user",
    "email": "1007a@example.com"
  },
  "created": "2021-10-07T22:16:16.4923965Z",
  "last_modified": "2021-10-07T22:16:37.4462418Z",
  "completed": "2021-10-07T22:16:37.4462418Z",
  "expires": "2022-01-05T22:16:32.1492867Z",
  "status": "completed",
  "metadata_url": "https://api-d.docusign.net/management/v2/organizations/e1b55b52-xxxx-xxxx-xxxx-8a7ff52dd8e0/exports/user_list/f7638356-xxxx-xxxx-xxxx-4935e87d88c1",
  "percent_completed": 100,
  "number_rows": 182,
  "size_bytes": 57403,
  "results": [
    {
      "id": "3cc60fdb-xxxx-xxxx-xxxx-1467a90d6d36",
      "site_id": 1,
      "url": "https://demo.docusign.net/restapi/v2/organization_exports/e1b55b52-xxxx-xxxx-xxxx-8a7ff52dd8e0/user_list/3cc60fdb-xxxx-xxxx-xxxx-1467a90d6d36",
      "number_rows": 182,
      "size_bytes": 57403
    }
  ],
  "success": true
}
```

## Step 5. Download the exported user data

After the export is complete and you’ve obtained the URL to retrieve the bulk export data, you can download a CSV file of that data.

The `results.url` value returned by the status request made in the previous step will contain the full path for the URL where you can download the CSV data, but you can also create the request manually by calling the [getUserListExport](/docs/admin-api/reference/bulkoperations/userexport/getuserlistexport) endpoint, as demonstrated in this example.

**`Bash`**

```bash title="Bash"
curl --request GET "${downloadUrl}" \
	"${Headers[@]}" \
	--output ${response2}
```

**`C#`**

```csharp title="C#"
request = (HttpWebRequest)WebRequest.Create(csvUrl);
request.Headers = headers;
request.Timeout = 10000;
request.AllowWriteStreamBuffering = false;

response = (HttpWebResponse)request.GetResponse();
string remaining = response.Headers.Get("X-RateLimit-Remaining");
string reset = response.Headers.Get("X-RateLimit-Reset");

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}

Stream stream = response.GetResponseStream();

FileStream fileStream = new FileStream(filePath, FileMode.Create);

byte[] buffer = new byte[256];
int count = stream.Read(buffer, 0, buffer.Length);

while (count > 0)
{
    fileStream.Write(buffer, 0, count);
    count = stream.Read(buffer, 0, buffer.Length);
}

fileStream.Close();
stream.Close();
response.Close();
```

**`Java`**

```java title="Java"
URL request_url = new URL(csvUri);

// Send Web request to download and save the exported CSV data
HttpsURLConnection.setFollowRedirects(true); // Defaults to true
HttpsURLConnection http_conn = (HttpsURLConnection) request_url.openConnection();
http_conn.setRequestProperty(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
http_conn.setRequestProperty(HttpHeaders.CONTENT_TYPE, "mutlipart/form-data");
http_conn.setRequestProperty(HttpHeaders.AUTHORIZATION, bearerAuthentication + accessToken);
http_conn.setInstanceFollowRedirects(true);

ClassLoader rawPath = Thread.currentThread().getContextClassLoader();
String rootDir = Paths.get(Objects.requireNonNull(rawPath.getResource("")).toURI()).toString();
// Set the save file path in the project root instead of the compiled folder and
// force forward slash scheme
rootDir = StringUtils.remove(rootDir, "target\\classes");
rootDir = StringUtils.remove(rootDir, "file:/");
rootDir = StringUtils.replace(rootDir, "\\", "/");

// opens input stream from the HTTP connection
InputStream inputStream = http_conn.getInputStream();
String saveFilePath = rootDir + "src/main/resources/ExportedUserData.csv";

// opens an output stream to save into file
FileOutputStream outputStream = FileUtils.openOutputStream(new File(saveFilePath));

int bytesRead;
byte[] buffer = new byte[bufferSize];
while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
}

outputStream.close();
inputStream.close();
http_conn.disconnect();
```

**`Node.js`**

```javascript title="Node.js"
const dataUrl = bulkExportResponse.data.results[0].url;
const requestOptions = {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${args.accessToken}`,
    'Content-Type': 'application/json'
  },
  responseType: 'stream'
};

const fileStream = fs.createWriteStream(args.filePath);
const response = await axios(dataUrl, requestOptions);
response.data.pipe(fileStream);

await new Promise((resolve, reject) => {
  fileStream.on('finish', () => {
    fileStream.end();
    resolve();
  });
  fileStream.on('error', (err) => {
    console.log(err);
    reject();
  });
});
```

**`PHP`**

```php title="PHP"
$csvUri = $organizationExportResponse[0]->getResults()[0]->getUrl();

$client = new Client();
$client->request(
    'GET',
    $csvUri,
    [
        'headers' => [
            'Authorization' => "bearer {$arguments['ds_access_token']}",
            'Accept' => 'application/json',
            'Content-Type' => "multipart/form-data; "
        ],
        'save_to' => "./demo_documents/ExportedUserData.csv"
    ]
);
```

**`PowerShell`**

```text title="PowerShell"
$uri3 = "https://demo.docusign.net/restapi/v2/organization_exports/$organizationId/user_list/$resultId"
$result3 = Invoke-WebRequest -headers $headers -Uri $uri3 -Method GET
$result3.Content
```

**`Python`**

```python title="Python"
api_client = ApiClient()

# Add headers to the API client object and the desired URL
headers = {"Authorization": "Bearer " + session["ds_access_token"]}
url = (
    "https://demo.docusign.net/restapi/v2/organization_exports/"
    f"{organization_id}/user_list/{obj_id}"
)

# Getting a response containing a csv file
response = api_client.request("GET", url, headers=headers)
```

**`Ruby`**

```ruby title="Ruby"
def get_exported_user_data(args, export_id)
  bulk_export_response, _status, headers = bulk_exports_api.get_user_list_export_with_http_info(args[:organization_id], export_id)

  remaining = headers['X-RateLimit-Remaining']
  reset = headers['X-RateLimit-Reset']

  if remaining && reset
    reset_date = Time.at(reset.to_i).utc
    puts "API calls remaining: #{remaining}"
    puts "Next Reset: #{reset_date}"
  end

  data_url = bulk_export_response.results[0].url

  uri = URI(data_url)

  req = Net::HTTP::Get.new(uri)
  req['Authorization'] = "Bearer #{args[:access_token]}"

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  http.request(req) do |response|
    File.open(args[:file_path], 'w') do |file|
      response.read_body do |chunk|
        file.write(chunk)
      end
    end
  end
end
```

## Expected response

**Important:** Make sure to replace the `resultId` placeholder with the `results.id` value you obtained in the previous step (or copy and paste the `results.url` value to completely replace the URL).

This API call will return a CSV file containing the list of user data, similar to this.

After downloading the CSV file, you can make edits to the list and either reimport it to update your user data or import it to a new account or organization. See [How to add users via bulk import](/docs/admin-api/how-to/add-users-bulk-import) for details.

> **Note**
>
> View the source code for this how-to on GitHub: [Bash](https://github.com/docusign/code-examples-bash/blob/master/examples/Admin/eg003BulkExportUserData.sh), [C#](https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/Admin/Examples/BulkExportUserData.cs), [Java](https://github.com/docusign/code-examples-java/blob/master/src/main/java/com/docusign/controller/admin/services/BulkExportUserDataService.java), [Node.js](https://github.com/docusign/code-examples-node/blob/master/lib/admin/examples/bulkExportUserData.js), [PHP](https://github.com/docusign/code-examples-php/blob/master/src/Services/Examples/Admin/BulkExportUserDataService.php), [PowerShell](https://github.com/docusign/code-examples-powershell/blob/master/examples/Admin/eg003BulkExportUserData.ps1), [Python](https://github.com/docusign/code-examples-python/blob/master/app/admin/examples/eg003_bulk_export_user_data.py), or [Ruby](https://github.com/docusign/code-examples-ruby/blob/master/app/services/admin_api/eg003_bulk_export_user_data_service.rb)

**`Sample response`**

```json title="Sample response"
"SiteID","AccountID","AccountName","APIUserName","FullName","FirstName","LastName","UserEmail","UserStatus","AddedDate","MembershipStatus","eSignPermissionProfile","CompanyName","JobTitle","AddressLine1","AdressLine2","City","StateRegionProvince","PostalCode","Country","Phone","Groups","EnableCLM","CLMPermissionProfile","IdentityProviderInfo","eSignPermissionProfileID","CLMPermissionProfileID"
"1","2255f473-xxxx-xxxx-xxxx-c07c9abc6d76","Test User","4c084b7a-xxxx-xxxx-xxxx-bf36f69e5c4e",1007 a","1007","a","1007a@example.com","Active","8/25/2021 12:3:04 AM","Active","profile1","","","","","","","","","","[Administrators],[group1],[Everyone]","False","","","10xxxx53",""
"1","2255f473-xxxx-xxxx-xxxx-c07c9abc6d76","Test User","e3e72e73-xxxx-xxxx-xxxx-064592a3453b",1007 a","1007","a","1007a@example.com","Active","8/24/2021 9:24:56 M","Active","profile2","","","","","","","","","","[Everyone]","False","","","10xxxx74",""
```

## Next steps

* Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects:    [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).
* See [How to create a new active eSignature user](/docs/admin-api/how-to/create-active-user)
* Learn [How to add users via bulk import](/docs/admin-api/how-to/add-users-bulk-import)
* See [Docusign Admin concepts](/docs/admin-api/admin101/concepts) for more information on Docusign Admin capabilities and features.
* See how to [Go-Live](/docs/admin-api/go-live) with a completed app and find the base path for API calls in the production environment.