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

# Update Subscription by token

> Update properties on an existing Subscription using its token. Commonly used to enable or disable subscription status when managing outside of the OneSignal SDK.

## Overview

Use this API to update an existing Subscription's properties.

This API can be useful if:

* You only know the `token` and `token_type` and want to update metadata or status flags directly.
* You are managing Subscription status outside of the OneSignal SDK. Like with a [custom preference page or unsubscribe page](/docs/en/create-custom-unsubscribe-page).

***

## How to use this API

To update a Subscription, you must know the `token_type` and the `token`.

The `token_type` is the [Subscription's type](/docs/en/server-sdk-reference#subscription-types) (e.g., `Email`, `SMS`, `iOSPush`, `AndroidPush`, etc.).

The `token` is the push token, email address, or phone number associated with the Subscription.

Ensure the `token` is valid and correctly formatted for the chosen `token_type`.

* **Email format:** Should be a valid email address that you confirmed can receive emails.
* **SMS format:** Phone number must be in [E.164 format](https://en.wikipedia.org/wiki/E.164).
* **iOSPush APNS token format:** 64 characters, hexadecimal characters only (0-9,a-f).
* **AndroidPush FCM token format:** Typically 163 characters, alphanumeric characters, may contain hyphens, colons and underscore.

<Warning>
  You **cannot** update the `token_type` and `token` of a Subscription with this API. If the `token_type` is incorrect:

  1. Use [Delete Subscription](/reference/delete-subscription) to remove the incorrect entry.
  2. Use [Create Subscription by alias](/reference/create-subscription) to recreate the subscription with the correct type.

  If multiple Subscriptions are found for the `token` and `token_type`, an `Http 400` error is returned with a list of subscription IDs that match the criteria.
</Warning>

***


## OpenAPI

````yaml PATCH /apps/{app_id}/subscriptions_by_token/{token_type}/{token}
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /apps/{app_id}/subscriptions_by_token/{token_type}/{token}:
    patch:
      summary: Update subscription By Token
      description: >-
        Update properties on an existing Subscription using its token. Commonly
        used to enable or disable subscription status when managing outside of
        the OneSignal SDK.
      operationId: update-subscription-by-token
      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
          required: true
        - name: token_type
          in: path
          description: The subscription channel type. Must match the format of the token.
          schema:
            type: string
            enum:
              - Email
              - SMS
              - iOSPush
              - AndroidPush
              - HuaweiPush
              - FireOSPush
              - WindowsPush
              - macOSPush
              - ChromeExtensionPush
              - ChromePush
              - FirefoxPush
              - SafariPush
          required: true
        - name: token
          in: path
          description: >-
            The push token, email address, or phone number associated with the
            subscription. Ensure the `token` is valid and correctly formatted
            for the chosen subscription `type`. Email format: Should be a valid
            email address that you confirmed can receive emails. SMS format:
            Phone number must be in [E.164
            format](https://en.wikipedia.org/wiki/E.164). iOSPush APNS token
            format: 64 characters, hexadecimal characters only (0-9,a-f).
            AndroidPush FCM token format: Typically 163 characters, alphanumeric
            characters, may contain hyphens, colons and underscore.
          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
              properties:
                subscription:
                  type: object
                  description: The subscription's properties.
                  required:
                    - type
                    - token
                  properties:
                    enabled:
                      type: boolean
                      description: >-
                        Indicates if the Subscription should be subscribed to
                        the message channel. Defaults to `true` if omitted. Set
                        to `false` to mark as unsubscribed.
                    notification_types:
                      type: integer
                      description: >-
                        Indicates the reason for the subscription status. Values
                        are updated automatically as events are detected by our
                        frontend SDKs but you should set this manually when
                        updating via our REST API. `1` is subscribed and `-31`
                        is reserved for unsubscribed via the API. See
                        [Subscriptions](/docs/subscriptions#notification-types).
                      format: int32
                    session_time:
                      type: integer
                      description: >-
                        The total amount of time the user has had the app open
                        in seconds.
                      format: int32
                    session_count:
                      type: integer
                      description: The total amount of times the user has opened the app.
                      format: int32
                    app_version:
                      type: string
                      description: >-
                        The version of your mobile app as detected by our
                        frontend SDKs or a value you set via our API. Our SDK
                        sets this based: Android - Android Studio `versionCode`
                        in your App `build.gradle`. iOS: Xcode App Version.
                    device_model:
                      type: string
                      description: The model of the user's device (e.g., iPhone 16).
                    device_os:
                      type: string
                      description: The device or browser's system version.
                    test_type:
                      type: integer
                      description: >-
                        Specifies the [APS environment
                        entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment)
                        used for generating the iOS push token. Omit, set to
                        `null` or `0` if the token was generated in a Production
                        environment (App Store & Test Flight builds). Set to `1`
                        for Development environment, `2` if it was generated in
                        an Ad-Hoc environment. This ensures OneSignal routes
                        notifications correctly based on the token’s source
                        environment.
                      format: int32
                    sdk:
                      type: string
                      description: >-
                        Set by our frontend SDK. Do not use this field.
                        Indicates the OneSignal SDK version.
                    web_auth:
                      type: string
                      description: >-
                        The web auth token set by our web SDK. Do not use this
                        field. See [Migrating to OneSignal from another
                        service](/docs/migrating-to-onesignal).
                    web_p256:
                      type: string
                      description: >-
                        The web 256 key set by our web SDK. Do not use this
                        field. See [Migrating to OneSignal from another
                        service](/docs/migrating-to-onesignal).
      responses:
        '202':
          description: '202'
          content:
            application/json:
              schema:
                type: object
                description: >-
                  The Subscription update request has been accepted
                  successfully. This process is asynchronous and may take a few
                  seconds to complete.
        '400':
          description: '400'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StructuredErrorResponse'
        '401':
          description: '401'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StructuredErrorResponse'
        '404':
          description: '404'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StructuredErrorResponse'
        '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/StructuredErrorResponse'
              example:
                errors:
                  - code: Rate Limit Exceeded
                    title: 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
      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 | Your OneSignal App ID in UUID v4 format.

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

            // string | The type of token to use when looking up the
            subscription. See Subscription Types.

            const tokenType: string = "Email";

            // string | The value of the token to lookup by (e.g., email
            address, phone number).

            const token: string = "user@example.com";

            // SubscriptionBody

            const subscriptionBody: Onesignal.SubscriptionBody = {
                subscription: {
                  id: "id_example",
                  type: "iOSPush",
                  token: "token_example",
                  enabled: true,
                  notification_types: 1,
                  session_time: 1,
                  session_count: 1,
                  sdk: "sdk_example",
                  device_model: "device_model_example",
                  device_os: "device_os_example",
                  rooted: true,
                  test_type: 1,
                  app_version: "app_version_example",
                  net_type: 1,
                  carrier: "carrier_example",
                  web_auth: "web_auth_example",
                  web_p256: "web_p256_example",
                },
              };

            try {
              const response = await apiInstance.updateSubscriptionByToken(appId, tokenType, token, subscriptionBody);
              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("updateSubscriptionByToken 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" # Your OneSignal App ID in UUID v4 format. 
                token_type = "Email" # The type of token to use when looking up the subscription. See Subscription Types. 
                token = "user@example.com" # The value of the token to lookup by (e.g., email address, phone number). 
                subscription_body = SubscriptionBody(
                    subscription=Subscription(
                        id="id_example",
                        type="iOSPush",
                        token="token_example",
                        enabled=True,
                        notification_types=1,
                        session_time=1,
                        session_count=1,
                        sdk="sdk_example",
                        device_model="device_model_example",
                        device_os="device_os_example",
                        rooted=True,
                        test_type=1,
                        app_version="app_version_example",
                        net_type=1,
                        carrier="carrier_example",
                        web_auth="web_auth_example",
                        web_p256="web_p256_example",
                    ),
                ) 

                try:
                    # Update subscription by token
                    api_response = api_instance.update_subscription_by_token(app_id, token_type, token, subscription_body)
                    pprint(api_response)
                except onesignal.ApiException as e:
                    print("Exception when calling DefaultApi->update_subscription_by_token: %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 | Your
            OneSignal App ID in UUID v4 format.

            $token_type = 'Email'; // string | The type of token to use when
            looking up the subscription. See Subscription Types.

            $token = 'user@example.com'; // string | The value of the token to
            lookup by (e.g., email address, phone number).

            $subscription_body = new \onesignal\client\model\SubscriptionBody();
            // \onesignal\client\model\SubscriptionBody


            try {
                $result = $apiInstance->updateSubscriptionByToken($app_id, $token_type, $token, $subscription_body);
                print_r($result);
            } catch (\onesignal\client\ApiException $e) {
                echo 'Exception when calling DefaultApi->updateSubscriptionByToken: ', $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->updateSubscriptionByToken: ', $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 | Your OneSignal App ID in UUID v4 format.
                tokenType := "Email" // string | The type of token to use when looking up the subscription. See Subscription Types.
                token := "user@example.com" // string | The value of the token to lookup by (e.g., email address, phone number).
                subscriptionBody := *onesignal.NewSubscriptionBody() // SubscriptionBody | 

                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.UpdateSubscriptionByToken(restAuth, appId, tokenType, token).SubscriptionBody(subscriptionBody).Execute()

                if err != nil {
                    fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.UpdateSubscriptionByToken``: %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 `UpdateSubscriptionByToken`: map[string]interface{}
                fmt.Fprintf(os.Stdout, "Response from `DefaultApi.UpdateSubscriptionByToken`: %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 | Your
            OneSignal App ID in UUID v4 format.

            token_type = 'Email' # String | The type of token to use when
            looking up the subscription. See Subscription Types.

            token = 'user@example.com' # String | The value of the token to
            lookup by (e.g., email address, phone number).

            subscription_body = OneSignal::SubscriptionBody.new #
            SubscriptionBody | 


            begin
              # Update subscription by token
              result = api_instance.update_subscription_by_token(app_id, token_type, token, subscription_body)
              p result
            rescue OneSignal::ApiError => e
              puts "Error when calling DefaultApi->update_subscription_by_token: #{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 | Your OneSignal App ID in UUID v4 format.
                String tokenType = "Email"; // String | The type of token to use when looking up the subscription. See Subscription Types.
                String token = "user@example.com"; // String | The value of the token to lookup by (e.g., email address, phone number).
                SubscriptionBody subscriptionBody = new SubscriptionBody(); // SubscriptionBody | 
                try {
                  Object result = apiInstance.updateSubscriptionByToken(appId, tokenType, token, subscriptionBody);
                  System.out.println(result);
                } catch (ApiException e) {
                  System.err.println("Exception when calling DefaultApi#updateSubscriptionByToken");
                  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 UpdateSubscriptionByTokenExample
                {
                    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 | Your OneSignal App ID in UUID v4 format.
                        var tokenType = "Email";  // string | The type of token to use when looking up the subscription. See Subscription Types.
                        var token = "user@example.com";  // string | The value of the token to lookup by (e.g., email address, phone number).
                        var subscriptionBody = new SubscriptionBody(); // SubscriptionBody | 

                        try
                        {
                            // Update subscription by token
                            Object result = apiInstance.UpdateSubscriptionByToken(appId, tokenType, token, subscriptionBody);
                            Debug.WriteLine(result);
                        }
                        catch (ApiException  e)
                        {
                            Debug.Print("Exception when calling DefaultApi.UpdateSubscriptionByToken: " + 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 token_type: &str = "Email";
                let token: &str = "user@example.com";
                let subscription_body: models::SubscriptionBody = todo!();

                match default_api::update_subscription_by_token(&configuration, app_id, token_type, token, subscription_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!("update_subscription_by_token failed: {:?}", e.error_messages());
                    }
                    Err(e) => eprintln!("update_subscription_by_token failed: {:?}", e),
                }
            }
components:
  schemas:
    StructuredErrorResponse:
      type: object
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/StructuredErrorItem'
    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.
    StructuredErrorItem:
      type: object
      required:
        - code
        - title
      properties:
        code:
          type: string
          description: >-
            Stable error-code identifier. Use this for programmatic branching in
            your integration.
        title:
          type: string
          description: >-
            Human-readable error message intended for logs and operator-facing
            surfaces.
        meta:
          type: object
          additionalProperties: true
          description: >-
            Optional structured details about this specific error. The shape of
            `meta` varies by `code` — for example, the create-user `Conflict`
            code returns `{ conflicting_aliases: { [alias_label]: alias_id } }`.

````