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

# Estimated recipients

> Returns the estimated number of recipients for a notification's targeting, without creating or sending anything.

## Overview

The Estimated recipients API allows you to check recipient counts based on the message's targeting settings, without creating or sending anything. The returned `count` reflects the same audience-size estimate you would see when composing a message in the OneSignal dashboard.

***

## How to Use this API

This API is most commonly used for checking how large a draft message's audience is going to be, before creating or sending it.

When making a request to this API, use a targeting-specific subset of message fields. `included_segments` is required. `excluded_segments`, `filters`, `include_aliases`, and `target_channel` narrow that segment-based audience further when present.

Use `target_channel` to select which platforms to count.

Other notification targeting fields (`include_subscription_ids` and the other raw subscription id/token fields, and the individual `isIos` / `isAndroid` / etc. platform flags) are not read by this API.

All non-targeting notification fields (content, delivery options, and so on) are accepted, but ignored.

***


## OpenAPI

````yaml POST /notifications/count-unsaved
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /notifications/count-unsaved:
    post:
      summary: Estimate notification recipients
      description: >-
        Returns the estimated number of recipients for a notification's
        targeting, without creating or sending anything.
      operationId: count-unsaved
      parameters:
        - 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:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - app_id
                - included_segments
              properties:
                app_id:
                  type: string
                  description: >-
                    The OneSignal App ID for your app. See [Keys &
                    IDs](/docs/en/keys-and-ids).
                  example: YOUR_APP_ID
                included_segments:
                  type: array
                  description: >-
                    Required. Segment names that define the base audience to
                    count. Combine with `excluded_segments`, `filters`,
                    `include_aliases`, and `target_channel` to narrow the
                    estimate. Example: `["Active Users", "Inactive Users"]`.
                    `"All"` is a shorthand for every subscribed user: if the
                    array includes `"All"` and the app has no segment named All,
                    the count includes all subscribers instead of looking up a
                    segment named All.
                  items:
                    type: string
                  example:
                    - Active Users
                excluded_segments:
                  type: array
                  description: >-
                    Segment names to exclude from the count. Users in these
                    segments are omitted even if they appear in
                    `included_segments`. Example: `["Active Users", "Inactive
                    Users"]`.
                  items:
                    type: string
                  example:
                    - Inactive Users
                filters:
                  type: array
                  nullable: true
                  description: >-
                    Filter expressions that further narrow the audience to
                    count. Each element is either a filter condition or an
                    `AND`/`OR` operator.
                  items:
                    type: object
                include_aliases:
                  type: object
                  nullable: true
                  description: >-
                    Narrow the count to users identified by aliases
                    (`external_id`, `onesignal_id`, or a custom alias). Keys are
                    alias labels and values are arrays of alias IDs. Example: `{
                    "external_id": ["extId1", "extId2"] }`. Limit of 2,000
                    entries per REST API call.
                  additionalProperties:
                    type: array
                    items:
                      type: string
                  example:
                    external_id:
                      - YOUR_USER_EXTERNAL_ID
                target_channel:
                  type: string
                  enum:
                    - push
                    - email
                    - sms
                  description: >-
                    Which platforms to count recipients for. Selects the same
                    default platforms Create notification would use for the
                    channel. Individual platform flags (`isIos`, `isAndroid`,
                    etc.) are not supported by this endpoint.
                  example: push
      responses:
        '200':
          description: >-
            Estimated recipient counts for the supplied targeting. No
            notification is created or sent.
          content:
            application/json:
              schema:
                type: object
                properties:
                  count:
                    type: integer
                    description: >-
                      The estimated audience size after applying the request's
                      targeting and platform selection.
                  uncapped_count:
                    type: integer
                    nullable: true
                    description: >-
                      The estimated audience size before the plan's web push
                      subscriber cap is applied. Present only when `cap_applied`
                      is `true`; `null` otherwise.
                  cap_applied:
                    type: boolean
                    description: >-
                      Whether `count` was reduced because the app is on a plan
                      that caps the number of web push subscribers it can send
                      to.
                  mobile_suppressed:
                    type: boolean
                    description: >-
                      The mobile equivalent of `cap_applied`. `true` when mobile
                      push recipients would be dropped because the org is over
                      its plan's mobile push subscriber cap. `false` when the
                      targeting does not include any mobile push platforms.
                  mobile_excluded_count:
                    type: integer
                    description: >-
                      How many mobile push recipients the `count` excludes due
                      to the plan's mobile push subscriber cap. `0` when
                      `mobile_suppressed` is `false`.
              example:
                count: 15420
                uncapped_count: null
                cap_applied: false
                mobile_suppressed: false
                mobile_excluded_count: 0
        '400':
          description: >-
            Bad request. The payload was rejected. Common causes include a
            missing `app_id` or `included_segments`.
          content:
            application/json:
              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'
      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);


            // EstimateNotificationRecipientsRequest

            const estimateNotificationRecipientsRequest:
            Onesignal.EstimateNotificationRecipientsRequest = null;


            try {
              const response = await apiInstance.estimateNotificationRecipients(estimateNotificationRecipientsRequest);
              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("estimateNotificationRecipients 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)
                estimate_notification_recipients_request = EstimateNotificationRecipientsRequest(None) 

                try:
                    # Estimate notification recipients
                    api_response = api_instance.estimate_notification_recipients(estimate_notification_recipients_request)
                    pprint(api_response)
                except onesignal.ApiException as e:
                    print("Exception when calling DefaultApi->estimate_notification_recipients: %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
            );

            $estimate_notification_recipients_request = new
            \onesignal\client\model\EstimateNotificationRecipientsRequest(); //
            \onesignal\client\model\EstimateNotificationRecipientsRequest


            try {
                $result = $apiInstance->estimateNotificationRecipients($estimate_notification_recipients_request);
                print_r($result);
            } catch (\onesignal\client\ApiException $e) {
                echo 'Exception when calling DefaultApi->estimateNotificationRecipients: ', $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->estimateNotificationRecipients: ', $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() {
                estimateNotificationRecipientsRequest := *onesignal.NewEstimateNotificationRecipientsRequest("AppId_example") // EstimateNotificationRecipientsRequest | 

                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.EstimateNotificationRecipients(restAuth).EstimateNotificationRecipientsRequest(estimateNotificationRecipientsRequest).Execute()

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

            estimate_notification_recipients_request =
            OneSignal::EstimateNotificationRecipientsRequest.new({app_id:
            'app_id_example'}) # EstimateNotificationRecipientsRequest | 


            begin
              # Estimate notification recipients
              result = api_instance.estimate_notification_recipients(estimate_notification_recipients_request)
              p result
            rescue OneSignal::ApiError => e
              puts "Error when calling DefaultApi->estimate_notification_recipients: #{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);
                EstimateNotificationRecipientsRequest estimateNotificationRecipientsRequest = new EstimateNotificationRecipientsRequest(); // EstimateNotificationRecipientsRequest | 
                try {
                  EstimateNotificationRecipientsSuccessResponse result = apiInstance.estimateNotificationRecipients(estimateNotificationRecipientsRequest);
                  System.out.println(result);
                } catch (ApiException e) {
                  System.err.println("Exception when calling DefaultApi#estimateNotificationRecipients");
                  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 EstimateNotificationRecipientsExample
                {
                    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 estimateNotificationRecipientsRequest = new EstimateNotificationRecipientsRequest(); // EstimateNotificationRecipientsRequest | 

                        try
                        {
                            // Estimate notification recipients
                            EstimateNotificationRecipientsSuccessResponse result = apiInstance.EstimateNotificationRecipients(estimateNotificationRecipientsRequest);
                            Debug.WriteLine(result);
                        }
                        catch (ApiException  e)
                        {
                            Debug.Print("Exception when calling DefaultApi.EstimateNotificationRecipients: " + 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 estimate_notification_recipients_request: models::EstimateNotificationRecipientsRequest = todo!();

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

````