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

# Create API key

> Use the OneSignal API to create a new Rich Authentication Token (App API Key) for a specific app. This guide explains how to authenticate with the Organization API key and configure optional IP allowlists using CIDR notation.

## Overview

Use this API to create a new **App API Key** (also called a **Rich Authentication Token**) for a specific OneSignal app. These keys are used to authenticate API requests at the app level and offer enhanced security features, including optional IP allowlisting.

<Note>
  For background on different OneSignal API keys, see [Keys & IDs](/docs/en/keys-and-ids).
</Note>

***

## How to use this API

Use your [Organization API Key](/docs/en/keys-and-ids#organization-api-key), to authenticate. This key is **different** from the standard REST API key.

### IP allowlisting

By default, the API key will not be restricted to any specific IP addresses. To enable IP allowlisting, you need to set the `ip_allowlist_mode` parameter to `explicit` and provide a list of allowed IP addresses in the `ip_allowlist` parameter.

If you want to set the explicit range of IPs that can use this API key, add them by setting `ip_allowlist_mode` to `explicit` and in `ip_allowlist` add the IPs in CIDRs notation as an array of string values.

***


## OpenAPI

````yaml POST /apps/{app_id}/auth/tokens
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /apps/{app_id}/auth/tokens:
    post:
      summary: Create API key
      description: >-
        Use the OneSignal API to create a new Rich Authentication Token (App API
        Key) for a specific app. This guide explains how to authenticate with
        the Organization API key and configure optional IP allowlists using CIDR
        notation.
      operationId: create-api-key
      parameters:
        - name: app_id
          in: path
          description: >-
            Your OneSignal App ID in UUID v4 format. See [Keys &
            IDs](/docs/en/keys-and-ids).
          schema:
            type: string
            default: YOUR_APP_ID
          required: true
        - name: Content-Type
          in: header
          required: true
          schema:
            type: string
            default: application/json
        - name: Authorization
          in: header
          description: >-
            Your Organization API key with prefix `Key `. See [Keys &
            IDs](/docs/en/keys-and-ids).
          required: true
          schema:
            type: string
            default: Key YOUR_ORGANIZATION_API_KEY
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: >-
                    An internal name you set to help organize and track API keys
                    (Rich Authentication Tokens). Maximum 128 characters.
                ip_allowlist_mode:
                  type: string
                  description: >-
                    Defaults to `disabled`, can be set to `explicit`. If set to
                    `explicit`, a list of network addresses in the form of CIDRs
                    has to be specified in the `ip_allowlist` parameter.
                  enum:
                    - disabled
                    - explicit
                ip_allowlist:
                  type: array
                  description: >-
                    An array of allowed networks in CIDRs notation. Only IPs in
                    those ranges will be permitted to use the API key.
                  items:
                    type: string
      responses:
        '200':
          description: >-
            The newly created API key token. `token_id` and `formatted_token`
            are populated. `formatted_token` is the secret and is returned only
            in this response. Store it now, or rotate the key later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiKeyToken'
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {}
              schema:
                type: object
                properties: {}
        '403':
          description: Forbidden. Your organization permissions do not allow this action.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
              example:
                errors:
                  - Current organization permissions do not allow this action.
        '404':
          description: App not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BasicErrorResponse'
              example:
                errors:
                  - App not found
        '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 the request. This
                header is optional and may be absent when a proxy or load
                balancer generates the 503.
              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({
                organizationApiKey: 'YOUR_ORGANIZATION_API_KEY',
            });
            const apiInstance = new Onesignal.DefaultApi(configuration);

            // string
            const appId: string = "YOUR_APP_ID";
            // CreateApiKeyRequest
            const createApiKeyRequest: Onesignal.CreateApiKeyRequest = {
                name: "name_example",
                ip_allowlist_mode: "disabled",
                ip_allowlist: [
                  "ip_allowlist_example",
                ],
              };

            try {
              const response = await apiInstance.createApiKey(appId, createApiKeyRequest);
              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("createApiKey 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 = "YOUR_APP_ID" 
                create_api_key_request = CreateApiKeyRequest(
                    name="name_example",
                    ip_allowlist_mode="disabled",
                    ip_allowlist=[
                        "ip_allowlist_example",
                    ],
                ) 

                try:
                    # Create API key
                    api_response = api_instance.create_api_key(app_id, create_api_key_request)
                    pprint(api_response)
                except onesignal.ApiException as e:
                    print("Exception when calling DefaultApi->create_api_key: %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: organization_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 = 'YOUR_APP_ID'; // string

            $create_api_key_request = new
            \onesignal\client\model\CreateApiKeyRequest(); //
            \onesignal\client\model\CreateApiKeyRequest


            try {
                $result = $apiInstance->createApiKey($app_id, $create_api_key_request);
                print_r($result);
            } catch (\onesignal\client\ApiException $e) {
                echo 'Exception when calling DefaultApi->createApiKey: ', $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->createApiKey: ', $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 := "YOUR_APP_ID" // string | 
                createApiKeyRequest := *onesignal.NewCreateApiKeyRequest() // CreateApiKeyRequest | 

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

                orgAuth := context.WithValue(context.Background(), onesignal.OrganizationApiKey, "YOUR_ORGANIZATION_API_KEY") // Organization API key is only required for creating new apps and other top-level endpoints

                resp, r, err := apiClient.DefaultApi.CreateApiKey(orgAuth, appId).CreateApiKeyRequest(createApiKeyRequest).Execute()

                if err != nil {
                    fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.CreateApiKey``: %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 `CreateApiKey`: CreateApiKeyResponse
                fmt.Fprintf(os.Stdout, "Response from `DefaultApi.CreateApiKey`: %v\n", resp)
            }
        - lang: ruby
          label: Ruby SDK
          source: >-
            require 'onesignal'

            # setup authorization

            OneSignal.configure do |config|
              # Configure Bearer authorization: organization_api_key
              config.organization_api_key = 'YOUR_ORGANIZATION_API_KEY'

            end


            api_instance = OneSignal::DefaultApi.new

            app_id = 'YOUR_APP_ID' # String | 

            create_api_key_request = OneSignal::CreateApiKeyRequest.new #
            CreateApiKeyRequest | 


            begin
              # Create API key
              result = api_instance.create_api_key(app_id, create_api_key_request)
              p result
            rescue OneSignal::ApiError => e
              puts "Error when calling DefaultApi->create_api_key: #{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: organization_api_key
                HttpBearerAuth organization_api_key = (HttpBearerAuth) defaultClient.getAuthentication("organization_api_key");
                organization_api_key.setBearerToken("YOUR_ORGANIZATION_API_KEY");

                DefaultApi apiInstance = new DefaultApi(defaultClient);
                String appId = "YOUR_APP_ID"; // String | 
                CreateApiKeyRequest createApiKeyRequest = new CreateApiKeyRequest(); // CreateApiKeyRequest | 
                try {
                  CreateApiKeyResponse result = apiInstance.createApiKey(appId, createApiKeyRequest);
                  System.out.println(result);
                } catch (ApiException e) {
                  System.err.println("Exception when calling DefaultApi#createApiKey");
                  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 CreateApiKeyExample
                {
                    public static void Main()
                    {
                        Configuration config = new Configuration();
                        config.BasePath = "https://api.onesignal.com";
                        // Configure Bearer token for authorization: organization_api_key
                        config.AccessToken = "YOUR_ORGANIZATION_API_KEY";

                        var apiInstance = new DefaultApi(config);
                        var appId = "YOUR_APP_ID";  // string | 
                        var createApiKeyRequest = new CreateApiKeyRequest(); // CreateApiKeyRequest | 

                        try
                        {
                            // Create API key
                            CreateApiKeyResponse result = apiInstance.CreateApiKey(appId, createApiKeyRequest);
                            Debug.WriteLine(result);
                        }
                        catch (ApiException  e)
                        {
                            Debug.Print("Exception when calling DefaultApi.CreateApiKey: " + 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.organization_api_key_token = Some("YOUR_ORGANIZATION_API_KEY".to_string());


                // Realistic values are pulled from the spec's `example:` fields where present.
                let app_id: &str = "YOUR_APP_ID";
                let create_api_key_request: models::CreateApiKeyRequest = todo!();

                match default_api::create_api_key(&configuration, app_id, create_api_key_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!("create_api_key failed: {:?}", e.error_messages());
                    }
                    Err(e) => eprintln!("create_api_key failed: {:?}", e),
                }
            }
components:
  schemas:
    ApiKeyToken:
      type: object
      description: >-
        An API key token (Rich Authentication Token). Each operation returns a
        different subset of these fields:


        - **GET tokens** returns every field except `formatted_token`.

        - **POST tokens** (create) returns `token_id` and `formatted_token`.

        - **POST tokens/{id}/rotate** returns `formatted_token` only.

        - **PATCH tokens/{id}** updates the record and returns an empty body.
        Re-fetch with GET to see the change.


        `formatted_token` is the REST API key. OneSignal returns it only on
        create and rotate, and does not store it. Save it immediately.
      properties:
        token_id:
          type: string
          format: uuid
          description: >-
            OneSignal-generated identifier for this API key. This is not the API
            key itself. Use `token_id` to manage the key in subsequent calls.
        name:
          type: string
          description: >-
            Internal name set when the key was created or last updated. Maximum
            128 characters.
        ip_allowlist_mode:
          type: string
          enum:
            - disabled
            - explicit
          description: >-
            When `explicit`, only requests from IP addresses matching
            `ip_allowlist` may use this key. Defaults to `disabled`.
        ip_allowlist:
          type: array
          items:
            type: string
          description: >-
            Allowed CIDR ranges. Only enforced when `ip_allowlist_mode` is
            `explicit`.
        created_at:
          type: string
          format: date-time
          description: ISO-8601 timestamp when the key was created.
        updated_at:
          type: string
          format: date-time
          description: ISO-8601 timestamp when the key was last updated.
        formatted_token:
          type: string
          description: >-
            The REST API key (Rich Authentication Token). Returned in plaintext
            only by the create and rotate endpoints, and only immediately after
            that call. OneSignal does not store the secret. If you lose it,
            rotate the key. See [Rotate API Key](/reference/rotate-api-key).
    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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.