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

# Export subscriptions CSV

> Generate a GZip-compressed CSV export of your current subscription data using this API endpoint.

## Overview

Use this endpoint to request a GZip-compressed CSV export of all your [Subscriptions data](/docs/en/subscriptions) from OneSignal. The export includes both default and optional user data fields, and supports filters to refine the dataset. The file is downloadable via a URL returned in the API response.

***

## How to use this API

By default, this exports all Subscriptions in the app.

### Optional filters

Narrow the export using any of these body parameters:

<ParamField body="segment_name" type="string">
  Only export Subscriptions from a specific segment. Segment membership rules determine which Subscription statuses are included. Use with `include_unsubscribed` to include unsubscribed Subscriptions.
</ParamField>

<ParamField body="last_active_since" type="string">
  A Unix timestamp in seconds. Export Subscriptions whose `last_session` is after this value. Example: use `1704067200` for Subscriptions active since January 1st, 2024.
</ParamField>

<ParamField body="include_unsubscribed" type="boolean" default="false">
  When exporting a segment, set to `true` to include unsubscribed Subscriptions alongside subscribed ones. By default, segment-filtered exports only return subscribed Subscriptions. This parameter has no effect when `segment_name` is not provided. See [Subscription statuses](/docs/en/subscriptions#subscription-statuses) for what counts as subscribed vs. unsubscribed.
</ParamField>

<ParamField body="extra_fields" type="string[]" default="[&#x22;external_user_id&#x22;, &#x22;country&#x22;, &#x22;timezone_id&#x22;]">
  Additional columns to include in the CSV. If you omit this parameter, the API defaults to `external_user_id`, `country`, and `timezone_id`.

  <Expandable title="Accepted values">
    <ParamField body="external_user_id" type="string">
      The user's External ID.
    </ParamField>

    <ParamField body="onesignal_id" type="string">
      OneSignal's user ID.
    </ParamField>

    <ParamField body="location" type="string">
      Adds the `lat` and `lon` coordinates if set.
    </ParamField>

    <ParamField body="country" type="string">
      The user's country in ISO 3166-1 Alpha 2 format.
    </ParamField>

    <ParamField body="ip" type="string">
      The IP address if detected. Can be IPv4 or IPv6 format.
    </ParamField>

    <ParamField body="rooted" type="boolean">
      Whether the Android device is rooted.
    </ParamField>

    <ParamField body="web_auth" type="string">
      The `web_auth` key for web push. Only available to OneSignal SDKs.
    </ParamField>

    <ParamField body="web_p256" type="string">
      The `web_p256` key for web push. Only available to OneSignal SDKs.
    </ParamField>

    <ParamField body="unsubscribed_at" type="string">
      The date and time the user last unsubscribed. They may resubscribe at any time. Check the `invalid_identifier` field to determine if they are currently subscribed.
    </ParamField>

    <ParamField body="notification_types" type="integer">
      Indicates the reason for the Subscription status. The frontend SDKs update this automatically. When updating via the REST API, set it manually. `1` is subscribed and `-31` is reserved for unsubscribed via the API. See [Subscriptions](/docs/en/subscriptions#notification-types).
    </ParamField>

    <ParamField body="timezone_id" type="string">
      The user's timezone in IANA format.
    </ParamField>
  </Expandable>
</ParamField>

### Example successful response

```json 200 OK theme={null}
{
  "csv_file_url": "https://onesignal.com/csv_exports/b2f7f966.../users_1849..._2024-11-10.csv.gz"
}
```

### Export time considerations

* Generation speed: \~2,000 records per second.
* File readiness: The `csv_file_url` may return a 404 until generation completes.
* Download retry: Poll the file URL at intervals until the file is ready.
* File expiration: The file remains available for 3 days after generation.
* Concurrency: Only one export per OneSignal account can run at a time. Wait until the `.csv.gz` file is downloaded before triggering another export.

### File not ready (404 response)

While the export is generating, requests to the `csv_file_url` return:

```xml theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchKey</Code>
  <Message>The specified key does not exist.</Message>
</Error>
```

Poll the URL until the file is ready. Base your retry interval on expected data volume and the \~2,000 records/second generation speed.

***

## CSV data contents

Every export includes a set of default columns. To add optional columns, use the [`extra_fields`](#optional-filters) parameter.

### Default columns

| Column               | Description                                                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | The Subscription ID.                                                                                                                    |
| `identifier`         | The push token, email address, or phone number depending on the Subscription type.                                                      |
| `session_count`      | The number of sessions recorded on this Subscription.                                                                                   |
| `language`           | The user's language in ISO 639-1 format.                                                                                                |
| `timezone`           | Deprecated. Use `timezone_id` instead.                                                                                                  |
| `game_version`       | The version of your app reported by this Subscription. Android reports the `versionCode`; iOS reports the `CFBundleShortVersionString`. |
| `device_os`          | The device's operating system version.                                                                                                  |
| `device_type`        | Integer representing the channel or device type. See [`device_type` values](#device_type-values).                                       |
| `device_model`       | The device's hardware string.                                                                                                           |
| `ad_id`              | Deprecated.                                                                                                                             |
| `tags`               | Custom key/value data.                                                                                                                  |
| `last_active`        | The last time this Subscription was active.                                                                                             |
| `playtime`           | The total time in seconds the user had the mobile app open.                                                                             |
| `amount_spent`       | The total amount in USD the user has spent on in-app purchases, if tracked.                                                             |
| `created_at`         | When this Subscription was created (the device, email address, or phone number was first registered).                                   |
| `invalid_identifier` | Boolean flag for unsubscribed state. `t` = Unsubscribed, `f` = Subscribed.                                                              |

#### `device_type` values

| Value     | Type                                |
| --------- | ----------------------------------- |
| `0`       | iOSPush                             |
| `1`       | AndroidPush                         |
| `2`       | FireOSPush                          |
| `3`       | WindowsPhoneLegacyPush (deprecated) |
| `4`       | ChromeExtensionPush                 |
| `5`       | ChromePush                          |
| `6`       | WindowsPush                         |
| `7`, `17` | SafariPush                          |
| `8`       | FirefoxPush                         |
| `9`       | macOSPush                           |
| `10`      | Alexa                               |
| `11`      | Email                               |
| `12`      | EdgePush                            |
| `13`      | HuaweiPush                          |
| `14`      | SMS                                 |

***


## OpenAPI

````yaml POST /players/csv_export
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /players/csv_export:
    post:
      summary: Export subscriptions CSV
      description: >-
        Generate a GZip-compressed CSV export of your current subscription data
        using this API endpoint.
      operationId: csv-export
      parameters:
        - name: app_id
          in: query
          description: >-
            Your OneSignal App ID in UUID v4 format. See [Keys &
            IDs](/docs/en/keys-and-ids).
          required: true
          schema:
            type: string
            default: YOUR_APP_ID
        - name: Authorization
          in: header
          description: >-
            Your App API key with prefix `Key `. See [Keys &
            IDs](/docs/en/keys-and-ids).
          required: true
          schema:
            type: string
            default: Key YOUR_APP_API_KEY
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                extra_fields:
                  type: array
                  description: Additional properties that you can include in the CSV.
                  default:
                    - external_user_id
                    - country
                    - timezone_id
                  items:
                    type: string
                    enum:
                      - external_user_id
                      - onesignal_id
                      - location
                      - country
                      - rooted
                      - ip
                      - web_auth
                      - web_p256
                      - unsubscribed_at
                      - notification_types
                      - timezone_id
                last_active_since:
                  type: string
                  description: >-
                    A Unix timestamp (in seconds) used to filter Subscriptions
                    based on recent activity. Only Subscriptions with a
                    `last_session` timestamp after this value will be included
                    in the export. Example: To export Subscriptions active since
                    January 1st, 2024, use `1704067200`.
                segment_name:
                  type: string
                  description: >-
                    The name of a specific segment to filter the export. Only
                    subscriptions that belong to this segment will be included
                    in the CSV. Omit this field to export all subscriptions in
                    the app.
                include_unsubscribed:
                  type: boolean
                  description: >-
                    When used with `segment_name`, set to `true` to include
                    unsubscribed subscriptions in the export. By default,
                    segment-filtered exports only return subscribed
                    subscriptions. This parameter has no effect when
                    `segment_name` is not provided.
                  default: false
      responses:
        '200':
          description: '200'
          content:
            application/json:
              schema:
                type: object
                properties:
                  csv_file_url:
                    type: string
                    description: >-
                      The URL to download the CSV file. The file is available
                      for 3 days after generation.
        '400':
          description: '400'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
              example:
                errors:
                  - 'Request is malformed: Failed to parse app_id from request'
        '429':
          description: >-
            Rate limit exceeded. Wait the number of seconds in the `Retry-After`
            header before retrying.
          headers:
            Retry-After:
              description: >-
                Number of seconds to wait before retrying the request. Always
                emitted on 429 responses.
              schema:
                type: integer
                minimum: 0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
              example:
                errors:
                  - API rate limit exceeded
        '503':
          description: >-
            Service temporarily unavailable. Retry after a short backoff. The
            body may be empty or non-JSON in some failure modes.
          headers:
            Retry-After:
              description: >-
                Number of seconds to wait before retrying. Optional — may be
                absent when the response is generated upstream.
              schema:
                type: integer
                minimum: 0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
              example:
                errors:
                  - Service temporarily unavailable
      deprecated: false
      security: []
      x-codeSamples:
        - lang: typescript
          label: Node.js SDK
          source: >-
            import Onesignal from '@onesignal/node-onesignal';


            const configuration = Onesignal.createConfiguration({
                restApiKey: 'YOUR_REST_API_KEY',
            });

            const apiInstance = new Onesignal.DefaultApi(configuration);


            // string | The app ID that you want to export devices from

            const appId: string = "00000000-0000-0000-0000-000000000000";

            // ExportSubscriptionsRequestBody (optional)

            const exportSubscriptionsRequestBody:
            Onesignal.ExportSubscriptionsRequestBody = {
                extra_fields: [
                  "extra_fields_example",
                ],
                last_active_since: "last_active_since_example",
                segment_name: "segment_name_example",
              };

            try {
              const response = await apiInstance.exportSubscriptions(appId, exportSubscriptionsRequestBody);
              console.log(response);
            } catch (e) {
              if (e instanceof Onesignal.ApiException) {
                // `e.errorMessages` flattens any error-envelope shape to a `string[]`;
                // the raw parsed body remains on `e.body`.
                console.error("exportSubscriptions failed: HTTP " + e.code, e.errorMessages);
              } else {
                throw e;
              }
            }
        - lang: python
          label: Python SDK
          source: >-
            import onesignal

            from onesignal.api import default_api

            from onesignal.models import *

            from pprint import pprint


            # See configuration.py for a list of all supported configuration
            parameters.

            # Some of the OneSignal endpoints require ORGANIZATION_API_KEY token
            for authorization, while others require REST_API_KEY.

            # We recommend adding both of them in the configuration page so that
            you will not need to figure it out yourself.

            configuration = onesignal.Configuration(
                rest_api_key = "YOUR_REST_API_KEY", # App REST API key required for most endpoints
                organization_api_key = "YOUR_ORGANIZATION_API_KEY" # Organization key is only required for creating new apps and other top-level endpoints
            )



            # Enter a context with an instance of the API client

            with onesignal.ApiClient(configuration) as api_client:
                # Create an instance of the API class
                api_instance = default_api.DefaultApi(api_client)
                app_id = "00000000-0000-0000-0000-000000000000" # The app ID that you want to export devices from 
                export_subscriptions_request_body = ExportSubscriptionsRequestBody(
                    extra_fields=[
                        "extra_fields_example",
                    ],
                    last_active_since="last_active_since_example",
                    segment_name="segment_name_example",
                ) 

                try:
                    # Export CSV of Subscriptions
                    api_response = api_instance.export_subscriptions(app_id, export_subscriptions_request_body=export_subscriptions_request_body)
                    pprint(api_response)
                except onesignal.ApiException as e:
                    print("Exception when calling DefaultApi->export_subscriptions: %s\n" % e)
                    print("Status Code: %s" % e.status)
                    print("Response Body: %s" % e.body)
        - lang: php
          label: PHP SDK
          source: >-
            <?php

            require_once(__DIR__ . '/vendor/autoload.php');



            // Configure Bearer authorization: rest_api_key

            $config = onesignal\client\Configuration::getDefaultConfiguration()
                                                            ->setRestApiKeyToken('YOUR_REST_API_KEY')
                                                            ->setOrganizationApiKeyToken('YOUR_ORGANIZATION_API_KEY');



            $apiInstance = new onesignal\client\Api\DefaultApi(
                // If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`.
                // This is optional, `GuzzleHttp\Client` will be used as default.
                new GuzzleHttp\Client(),
                $config
            );

            $app_id = '00000000-0000-0000-0000-000000000000'; // string | The
            app ID that you want to export devices from

            $export_subscriptions_request_body = new
            \onesignal\client\model\ExportSubscriptionsRequestBody(); //
            \onesignal\client\model\ExportSubscriptionsRequestBody


            try {
                $result = $apiInstance->exportSubscriptions($app_id, $export_subscriptions_request_body);
                print_r($result);
            } catch (\onesignal\client\ApiException $e) {
                echo 'Exception when calling DefaultApi->exportSubscriptions: ', $e->getMessage(), PHP_EOL;
                echo 'Status Code: ', $e->getCode(), PHP_EOL;
                // getErrorMessages() flattens any error-envelope shape to a string[];
                // the raw body remains on getResponseBody().
                echo 'Error Messages: ', implode(', ', $e->getErrorMessages()), PHP_EOL;
                echo 'Response Body: ', $e->getResponseBody(), PHP_EOL;
            } catch (\Exception $e) {
                echo 'Exception when calling DefaultApi->exportSubscriptions: ', $e->getMessage(), PHP_EOL;
            }
        - lang: go
          label: Go SDK
          source: |-
            package main

            import (
                "context"
                "fmt"
                "os"

                "github.com/OneSignal/onesignal-go-api/v5"
            )

            func main() {
                appId := "00000000-0000-0000-0000-000000000000" // string | The app ID that you want to export devices from
                exportSubscriptionsRequestBody := *onesignal.NewExportSubscriptionsRequestBody() // ExportSubscriptionsRequestBody |  (optional)

                configuration := onesignal.NewConfiguration()
                apiClient := onesignal.NewAPIClient(configuration)

                restAuth := context.WithValue(context.Background(), onesignal.RestApiKey, "YOUR_REST_API_KEY") // App REST API key required for most endpoints

                resp, r, err := apiClient.DefaultApi.ExportSubscriptions(restAuth, appId).ExportSubscriptionsRequestBody(exportSubscriptionsRequestBody).Execute()

                if err != nil {
                    fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.ExportSubscriptions``: %v\n", err)
                    fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
                    if apiErr, ok := err.(*onesignal.GenericOpenAPIError); ok {
                        // ErrorMessages() flattens any error-envelope shape to a []string;
                        // the raw body remains on Body().
                        fmt.Fprintf(os.Stderr, "Error Messages: %v\n", apiErr.ErrorMessages())
                        fmt.Fprintf(os.Stderr, "Response Body: %s\n", apiErr.Body())
                    }
                }
                // response from `ExportSubscriptions`: ExportSubscriptionsSuccessResponse
                fmt.Fprintf(os.Stdout, "Response from `DefaultApi.ExportSubscriptions`: %v\n", resp)
            }
        - lang: ruby
          label: Ruby SDK
          source: >-
            require 'onesignal'

            # setup authorization

            OneSignal.configure do |config|
              # Configure Bearer authorization: rest_api_key
              config.rest_api_key = 'YOUR_REST_API_KEY'

            end


            api_instance = OneSignal::DefaultApi.new

            app_id = '00000000-0000-0000-0000-000000000000' # String | The app
            ID that you want to export devices from

            opts = {
              export_subscriptions_request_body: OneSignal::ExportSubscriptionsRequestBody.new # ExportSubscriptionsRequestBody | 
            }


            begin
              # Export CSV of Subscriptions
              result = api_instance.export_subscriptions(app_id, opts)
              p result
            rescue OneSignal::ApiError => e
              puts "Error when calling DefaultApi->export_subscriptions: #{e}"
              puts "Status Code: #{e.code}"
              # `e.error_messages` flattens any error-envelope shape to an Array<String>;
              # the raw body remains on `e.response_body`.
              puts "Error Messages: #{e.error_messages}"
              puts "Response Body: #{e.response_body}"
            end
        - lang: java
          label: Java SDK
          source: |-
            // Import classes:
            import com.onesignal.client.ApiClient;
            import com.onesignal.client.ApiException;
            import com.onesignal.client.Configuration;
            import com.onesignal.client.auth.*;
            import com.onesignal.client.model.*;
            import com.onesignal.client.api.DefaultApi;

            public class Example {
              public static void main(String[] args) {
                ApiClient defaultClient = Configuration.getDefaultApiClient();
                defaultClient.setBasePath("https://api.onesignal.com");
                
                // Configure HTTP bearer authorization: rest_api_key
                HttpBearerAuth rest_api_key = (HttpBearerAuth) defaultClient.getAuthentication("rest_api_key");
                rest_api_key.setBearerToken("YOUR_REST_API_KEY");

                DefaultApi apiInstance = new DefaultApi(defaultClient);
                String appId = "00000000-0000-0000-0000-000000000000"; // String | The app ID that you want to export devices from
                ExportSubscriptionsRequestBody exportSubscriptionsRequestBody = new ExportSubscriptionsRequestBody(); // ExportSubscriptionsRequestBody | 
                try {
                  ExportSubscriptionsSuccessResponse result = apiInstance.exportSubscriptions(appId, exportSubscriptionsRequestBody);
                  System.out.println(result);
                } catch (ApiException e) {
                  System.err.println("Exception when calling DefaultApi#exportSubscriptions");
                  System.err.println("Status code: " + e.getCode());
                  // getErrorMessages() flattens any error-envelope shape to a List<String>;
                  // the raw body remains on getResponseBody().
                  System.err.println("Error messages: " + e.getErrorMessages());
                  System.err.println("Reason: " + e.getResponseBody());
                  System.err.println("Response headers: " + e.getResponseHeaders());
                  e.printStackTrace();
                }
              }
            }
        - lang: csharp
          label: C# SDK
          source: |-
            using System;
            using System.Collections.Generic;
            using System.Diagnostics;
            using OneSignalApi.Api;
            using OneSignalApi.Client;
            using OneSignalApi.Model;

            namespace Example
            {
                public class ExportSubscriptionsExample
                {
                    public static void Main()
                    {
                        Configuration config = new Configuration();
                        config.BasePath = "https://api.onesignal.com";
                        // Configure Bearer token for authorization: rest_api_key
                        config.AccessToken = "YOUR_REST_API_KEY";

                        var apiInstance = new DefaultApi(config);
                        var appId = "00000000-0000-0000-0000-000000000000";  // string | The app ID that you want to export devices from
                        var exportSubscriptionsRequestBody = new ExportSubscriptionsRequestBody(); // ExportSubscriptionsRequestBody |  (optional) 

                        try
                        {
                            // Export CSV of Subscriptions
                            ExportSubscriptionsSuccessResponse result = apiInstance.ExportSubscriptions(appId, exportSubscriptionsRequestBody);
                            Debug.WriteLine(result);
                        }
                        catch (ApiException  e)
                        {
                            Debug.Print("Exception when calling DefaultApi.ExportSubscriptions: " + e.Message );
                            Debug.Print("Status Code: "+ e.ErrorCode);
                            // e.ErrorMessages flattens any error-envelope shape to an IReadOnlyList<string>;
                            // the raw body remains on e.ErrorContent.
                            Debug.Print("Error Messages: " + string.Join(", ", e.ErrorMessages));
                            Debug.Print("Response Body: " + e.ErrorContent);
                            Debug.Print(e.StackTrace);
                        }
                    }
                }
            }
        - lang: rust
          label: Rust SDK
          source: |-
            use onesignal_rust_api::apis::configuration::Configuration;
            use onesignal_rust_api::apis::default_api;

            use onesignal_rust_api::models;


            #[tokio::main]
            async fn main() {
                let mut configuration = Configuration::new();
                configuration.rest_api_key_token = Some("YOUR_REST_API_KEY".to_string());


                // Realistic values are pulled from the spec's `example:` fields where present.
                let app_id: &str = "00000000-0000-0000-0000-000000000000";
                let export_subscriptions_request_body: Option<models::ExportSubscriptionsRequestBody> = None;

                match default_api::export_subscriptions(&configuration, app_id, export_subscriptions_request_body).await {
                    Ok(resp) => println!("{:?}", resp),
                    Err(e @ onesignal_rust_api::apis::Error::ResponseError(_)) => {
                        // `e.error_messages()` flattens any error-envelope shape to a Vec<String>;
                        // the raw response remains on the ResponseError variant.
                        eprintln!("export_subscriptions failed: {:?}", e.error_messages());
                    }
                    Err(e) => eprintln!("export_subscriptions failed: {:?}", e),
                }
            }
components:
  schemas:
    BasicErrorResponse:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
          description: One or more human-readable error messages.
        success:
          type: boolean
          description: >-
            Present (and `false`) on some endpoints (notifications, templates,
            segments). Not emitted by every endpoint.
        reference:
          type: array
          items:
            type: string
          description: >-
            Documentation URL fragments related to the error. Only emitted by
            the API-key auth error helpers.

````