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

# Message history

> View which subscriptions received a particular message

## Overview

This API enables you to retrieve all [Subscriptions](/docs/en/subscriptions) that received a specific push notification or email. You can access the notification's history for up to seven days after it was sent. Please note that notifications sent to fewer than 1,000 recipients will not record a "received" event, but they will still record "sent" events.

***

## How to Use this API

1. Submit a request to generate a report.

2. Decide delivery method

   * After receiving a successful response, **poll the destination URL** until the file becomes available. Exports typically complete within 1-3 minutes; we recommend a 10-second polling interval.
   * Alternatively, you can opt to receive an email to the address specified in the optional `email` parameter when the report is ready.

### Requirements

* A [OneSignal Professional or Enterprise Plan](https://onesignal.com/pricing).
* Enabled the "Send History via OneSignal API" option in Settings -> Integrations; notifications sent before this setting is enabled can't be retrieved.
* Requests must be made within seven days of sending the notification.

### Polling

Use the `csv_file_url` property in the response to test if the report is complete. If you receive a '403' error response, retry fetching the file after a short period; it only means we're still generating the report.

### Sample Report

The generated report is a simple CSV file that can be imported into any system for further processing.

```csv report.csv theme={null}
player_id,onesignal_id,external_id,target_channel,timestamp
"2c4fac95-7dfb-4113-9347-aba3a92ff557","ccddf35a-1233-4423-8a57-ac8c4b38eb81","a07aec27-2586-4b92-a24f-62660a1517fa","push","1628189160"
"68f5cf73-b20a-4de9-b6ee-79a863b8e7d8","d2f9f2f8-94af-4942-8183-115cef1213d5","4b66359f-3d94-4a73-806d-8ef5f0430b3d","push","1628187816"

```

### Limitations

* Querying for `opens` events are not supported.
* The `timestamp` column is included only for `clicked` events.

***


## OpenAPI

````yaml POST /notifications/{message_id}/history
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /notifications/{message_id}/history:
    post:
      summary: Message history
      description: View which subscriptions received a particular message
      operationId: message-history
      parameters:
        - name: message_id
          in: path
          description: >-
            The identifier of the message in UUID v4 format. Get this `id` in
            the response of your Create Message API request, the [View Messages
            API](/reference/view-messages), and in your OneSignal dashboard
            Message Reports.
          schema:
            type: string
          required: true
        - 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
              required:
                - app_id
                - events
              properties:
                app_id:
                  type: string
                  description: >-
                    Your OneSignal App ID in UUID v4 format. See [Keys &
                    IDs](/docs/en/keys-and-ids).
                  default: YOUR_APP_ID
                events:
                  type: string
                  description: >-
                    Specifies the type of event to retrieve. `sent` — retrieves
                    all subscriptions sent the specified message. Note: sent
                    events are not recorded for messages targeting fewer than
                    1,000 recipients. `clicked` — retrieves all subscriptions
                    that interacted with the message. Note: There isn't a
                    recipient count threshold for tracking clicked event.
                  default: sent
                email:
                  type: string
                  description: The email address in which to deliver the report.
      responses:
        '202':
          description: >-
            Accepted. The history-export job was enqueued. The export is
            delivered asynchronously to the configured S3 destination.
          content:
            application/json:
              examples:
                Result:
                  value:
                    success: true
                    destination_url: https://onesignal-aws-link.csv
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                    default: true
                  destination_url:
                    type: string
                    example: https://onesignal-aws-link.csv
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value:
                    errors:
                      - param `email` must be a valid email
                    success: false
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
        '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
      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 \"id\" of the message found in the Notification
            object

            const notificationId: string =
            "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88";

            // GetNotificationHistoryRequestBody

            const getNotificationHistoryRequestBody:
            Onesignal.GetNotificationHistoryRequestBody = {
                events: "sent",
                email: "email_example",
                app_id: "app_id_example",
              };

            try {
              const response = await apiInstance.getNotificationHistory(notificationId, getNotificationHistoryRequestBody);
              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("getNotificationHistory 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_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)
                notification_id = "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88" # The \"id\" of the message found in the Notification object 
                get_notification_history_request_body = GetNotificationHistoryRequestBody(
                    events="sent",
                    email="email_example",
                    app_id="app_id_example",
                ) 

                # example passing only required values which don't have defaults set
                try:
                    # Notification History
                    api_response = api_instance.get_notification_history(notification_id, get_notification_history_request_body)
                    pprint(api_response)
                except onesignal.ApiException as e:
                    print("Exception when calling DefaultApi->get_notification_history: %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
            );

            $notification_id = 'b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88'; // string
            | The \"id\" of the message found in the Notification object

            $get_notification_history_request_body = new
            \onesignal\client\model\GetNotificationHistoryRequestBody(); //
            \onesignal\client\model\GetNotificationHistoryRequestBody


            try {
                $result = $apiInstance->getNotificationHistory($notification_id, $get_notification_history_request_body);
                print_r($result);
            } catch (\onesignal\client\ApiException $e) {
                echo 'Exception when calling DefaultApi->getNotificationHistory: ', $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->getNotificationHistory: ', $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() {
                notificationId := "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88" // string | The \"id\" of the message found in the Notification object
                getNotificationHistoryRequestBody := *onesignal.NewGetNotificationHistoryRequestBody() // GetNotificationHistoryRequestBody | 

                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.GetNotificationHistory(restAuth, notificationId).GetNotificationHistoryRequestBody(getNotificationHistoryRequestBody).Execute()

                if err != nil {
                    fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.GetNotificationHistory``: %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 `GetNotificationHistory`: NotificationHistorySuccessResponse
                fmt.Fprintf(os.Stdout, "Response from `DefaultApi.GetNotificationHistory`: %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_BEARER_TOKEN'

            end


            api_instance = OneSignal::DefaultApi.new

            notification_id = 'b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88' # String |
            The \"id\" of the message found in the Notification object

            get_notification_history_request_body =
            OneSignal::GetNotificationHistoryRequestBody.new #
            GetNotificationHistoryRequestBody | 


            begin
              # Notification History
              result = api_instance.get_notification_history(notification_id, get_notification_history_request_body)
              p result
            rescue OneSignal::ApiError => e
              puts "Error when calling DefaultApi->get_notification_history: #{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("BEARER TOKEN");

                DefaultApi apiInstance = new DefaultApi(defaultClient);
                String notificationId = "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88"; // String | The \"id\" of the message found in the Notification object
                GetNotificationHistoryRequestBody getNotificationHistoryRequestBody = new GetNotificationHistoryRequestBody(); // GetNotificationHistoryRequestBody | 
                try {
                  NotificationHistorySuccessResponse result = apiInstance.getNotificationHistory(notificationId, getNotificationHistoryRequestBody);
                  System.out.println(result);
                } catch (ApiException e) {
                  System.err.println("Exception when calling DefaultApi#getNotificationHistory");
                  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 GetNotificationHistoryExample
                {
                    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_BEARER_TOKEN";

                        var apiInstance = new DefaultApi(config);
                        var notificationId = "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88";  // string | The \"id\" of the message found in the Notification object
                        var getNotificationHistoryRequestBody = new GetNotificationHistoryRequestBody(); // GetNotificationHistoryRequestBody | 

                        try
                        {
                            // Notification History
                            NotificationHistorySuccessResponse result = apiInstance.GetNotificationHistory(notificationId, getNotificationHistoryRequestBody);
                            Debug.WriteLine(result);
                        }
                        catch (ApiException  e)
                        {
                            Debug.Print("Exception when calling DefaultApi.GetNotificationHistory: " + 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 notification_id: &str = "b3a0c8bd-3a4c-4b22-9a73-3f1a8c2d1b88";
                let get_notification_history_request_body: models::GetNotificationHistoryRequestBody = todo!();

                match default_api::get_notification_history(&configuration, notification_id, get_notification_history_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!("get_notification_history failed: {:?}", e.error_messages());
                    }
                    Err(e) => eprintln!("get_notification_history 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.

````