All Products
Search
Document Center

Chat App Message Service:Best practices for authentication templates

Last Updated:Sep 03, 2026

Create and integrate WhatsApp authentication templates that deliver one-time passwords (OTPs) via a copy code button or one-tap autofill button.

Background information

WhatsApp launched authentication templates with OTP buttons on May 1, 2023. Since May 29, 2023, all new authentication templates must include an OTP button, as defined in WhatsApp message templates.

Template composition

An OTP authentication template consists of these components:

Component

Content

Required

Preset text

<VERIFICATION_CODE> is your verification code.

Yes

Security recommendation

For your security, do not share this code.

No

Expiration warning

This code expires in <NUM_MINUTES> minutes.

No

Button

A copy code button or a one-tap autofill button.

Yes

Example:

Authentication template OTP example

Template limits

Constraint

Detail

Allowed content

Preset text and a button only

Prohibited content

URLs, media resources (images, audios, videos, files), and emojis

OTP maximum length

15 characters

Button types

An authentication template must contain one of the following button types:

Copy code button

When a user taps the copy code button, the OTP is copied to the clipboard. The user then switches to your app and pastes the OTP into the app interface.

One-tap autofill button

When a user taps the one-tap autofill button, your app is automatically loaded and the OTP is passed to the app.

Note

The one-tap autofill button provides the best user experience but is Android-only. It requires a Handshake and a configured App signing key hash.

Best practices

  • Confirm the WhatsApp phone numbers before you send OTPs.

  • Make it clear to users that OTPs will be delivered to their WhatsApp phone numbers, especially if you provide users with multiple options to receive OTPs.

  • After your app receives the OTP, whether by user paste or by one-tap autofill, make it clear to users that your app has received the code.

Parameters

Use the following parameters to create an authentication template.

Required parameters

Parameter

Type

Description

Example

COMPONENTS

Array

Array of objects describing the template components.

-

LANGUAGE

String

The language code of the template.

en_US

NAME

String

The template name. Supports only lowercase letters, underscores (_), and digits. Maximum 60 characters.

verification_code

WHATSAPP_BUSINESS_ACCOUNT_ID

String

The WhatsApp Business Account (WABA) ID to associate with the template.

106\*\*\*\*\*\*\*\*\*\*\*06

OTP_TYPE

Enum

The button type. Set this parameter to COPY_CODE for the copy code button or ONE_TAP for the one-tap autofill button.

ONE_TAP

COPY_CODE_BUTTON_TEXT

String

The text of the copy code button. The value can be up to 25 characters in length.

Copy Code

Important

You must specify the COPY_CODE_BUTTON_TEXT parameter even if the template uses the one-tap autofill button. If the handshake cannot be validated, the authentication template message will fall back to displaying the copy code button with this text.

Optional parameters

Parameter

Type

Description

Example

ADD_SECURITY_RECOMMENDATION

Boolean

If true, includes the fixed text: *For your security, do not share this code.* If false, excludes it. This text cannot be customized.

true

CODE_EXPIRATION_MINUTES

Integer

OTP validity period in minutes. Valid values: 1 to 90. If unspecified, no expiration warning is displayed.

5

One-tap autofill parameters

These parameters are required only when OTP_TYPE is ONE_TAP.

Parameter

Type

Description

Example

ONE_TAP_BUTTON_TEXT

String

The text of the one-tap autofill button. The value can be up to 25 characters in length.

Autofill

PACKAGE_NAME

String

The package name of the Android app.

com.example.myapplication

SIGNATURE_HASH

String

Your app signing key hash, as described in App signing key hash.

K8a%2FAINcGX7

App signing key hash

To use the one-tap autofill button, include your app signing key hash in the components array.

To calculate your hash, follow the instructions provided by Google in Computing your app's hash string.

If you download your app signing key certificate as instructed by Google, you can use the certificate together with the sms_retriever_hash_v9.sh shell script to calculate the hash.

Handshake

Your app must perform a handshake with WhatsApp before sending an authentication template message with the one-tap autofill button:

  1. A user of your app requests an OTP and chooses to receive it through their WhatsApp phone number.

  2. Your app performs a handshake by sending an intent to the WhatsApp client.

  3. Your app calls the API to send an authentication template message.

  4. The WhatsApp client receives the message and runs eligibility checks.

  5. If the message passes all eligibility checks, the WhatsApp client starts the intent and displays the message to the user.

  6. When the user taps the one-tap autofill button, the WhatsApp client loads your app and passes the OTP to your app.

Note

If you do not perform a handshake before the message is sent, or if the message fails an eligibility check, the delivered message will contain a copy code button instead of a one-tap autofill button.

Eligibility checks

The WhatsApp client runs these checks on each authentication template message. If any check fails, the one-tap autofill button falls back to the copy code button.

#

Check

Detail

1

Handshake timing

The handshake is initiated within 10 minutes before the message is sent.

2

Package name match

The app package name in the message matches the app package name set on the intent. The app package name in the message is the value of package_name in the components array that is set when you create the authentication template. The WhatsApp client determines whether the app package names match by using the getCreatorPackage method called on the PendingIntent object provided by your app.

3

Signing key hash match

The app signing key hash in the message (the value of signature_hash in the components array) matches the app signing key hash of your app.

4

Button text presence

The message contains the text of the one-tap autofill button.

5

Activity defined

Your app defines an Activity to receive the OTP.

Android notifications

An Android notification for a WhatsApp authentication template message appears on the user's device only when all of the following conditions are met:

#

Condition

1

The user is logged in to the WhatsApp app or the WhatsApp Business app with the phone number or account that receives the message.

2

The user is logged in to your app.

3

The Android operating system is KitKat (4.4, API 19) or later.

4

Show notifications is enabled under Settings > Notifications in the WhatsApp app or WhatsApp Business app.

5

Device-level notification is enabled for the WhatsApp app or WhatsApp Business app.

6

Previous messages between the user and your enterprise in the WhatsApp app or WhatsApp Business app are not muted.

Client implementation

Implement the activity, class, and handshake in your Android app as follows.

Activity

Declare an activity and intent filter to receive the OTP. The intent filter must contain the action com.whatsapp.otp.OTP_RETRIEVED.

The WhatsApp client initiates this activity immediately after the message is received and passes all eligibility checks.

Public class

Define the activity public class to accept the OTP passed to your app.

Initiate a handshake

The following Java example initiates a handshake by sending an intent to both the WhatsApp app and the WhatsApp Business app:

public void sendOtpIntentToWhatsApp() {
   // Send OTP_REQUESTED intent to both WA and WA Business App
   sendOtpIntentToWhatsApp("com.whatsapp");
   sendOtpIntentToWhatsApp("com.whatsapp.w4b");
}

private void sendOtpIntentToWhatsApp(String packageName) {

  /**
  * Starting with Build.VERSION_CODES.S, it will be required to explicitly
  * specify the mutability of  PendingIntents on creation with either
  * (@link #FLAG_IMMUTABLE} or FLAG_MUTABLE
  */
  int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? FLAG_IMMUTABLE : 0;
  PendingIntent pi = PendingIntent.getActivity(
      getApplicationContext(),
      0,
      new Intent(),
      flags);


  // Send OTP_REQUESTED intent to WhatsApp
  Intent intentToWhatsApp = new Intent();
  intentToWhatsApp.setPackage(packageName);
  intentToWhatsApp.setAction("com.whatsapp.otp.OTP_REQUESTED");
  // WA will use this to verify the identity of the caller app.
  Bundle extras = intentToWhatsApp.getExtras();
  if (extras == null) {
     extras = new Bundle();
  }
  extras.putParcelable("_ci_", pi);
  intentToWhatsApp.putExtras(extras);
  getApplicationContext().sendBroadcast(intentToWhatsApp);
}

Error signals

If a message fails an eligibility check, the one-tap autofill button falls back to the copy code button. Notifications may also be blocked by the device or WhatsApp client. For debugging, the WhatsApp client sends error information through the com.whatsapp.otp.OTP_ERROR intent, returning an error key and message instead of an OTP.

Note

Some error signals appear only in an Android emulator.

Error key

Description

Emulator only

incompatible_os_version

The Android version is not compatible. This error occurs when you initiate a handshake by sending the com.whatsapp.otp.OTP_REQUESTED intent but the device runs an Android version earlier than API 19.

No

incorrect_signature_hash

The signature hash is incorrect. This error occurs when you initiate a handshake and the WhatsApp client receives an authentication template message with the one-tap autofill button, but the package name in the message does not include the correct signature hash.

Yes

missing_handshake_or_disorder

The handshake or operation instruction is lacking. This error occurs when the WhatsApp client receives an authentication template message with the one-tap autofill button but no handshake has been initiated.

No

otp_request_expired

The OTP request has expired. This error occurs when you initiate a handshake but the authentication template message is delivered to the user more than 10 minutes later. The one-tap autofill button is replaced with the copy code button.

No

whatsapp_message_notification_disabled

Message notifications are disabled in the WhatsApp app or WhatsApp Business app. This error occurs when you initiate a handshake but the user has disabled message notifications in the WhatsApp client.

Yes

whatsapp_notification_disabled

WhatsApp notifications are disabled on the device. This error occurs when you initiate a handshake but the user has disabled notifications for the WhatsApp app or WhatsApp Business app at the device level.

Yes

Error signal integration

Error signals are delivered through broadcasted intents. To receive them, implement BroadcastReceiver.

In manifest.xml

<receiver
 android:name=".app.otp.OtpErrorReceiver"
 android:enabled="true"
 android:exported="true" >
   <intent-filter>
       <action android:name="com.whatsapp.otp.OTP_ERROR"/>
   </intent-filter>
</receiver>

In receiver class

public class OtpErrorReceiver extends BroadcastReceiver {
    public static final String OTP_ERROR_KEY = "error";
    public static final String OTP_ERROR_MESSAGE_KEY = "error_message";

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            PendingIntent pendingIntent = intent.getParcelableExtra("_ci_");
            if (pendingIntent != null) {
                String packageName = pendingIntent.getCreatorPackage();
                if (packageName.equalsIgnoreCase("com.whatsapp")
                        || packageName.equalsIgnoreCase("com.whatsapp.w4b")) {
                    String otpErrorKey = intent.getStringExtra(OTP_ERROR_KEY);
                    String otpErrorMessage = intent.getStringExtra(OTP_ERROR_MESSAGE_KEY);
                    // Handle errors
                }
            }
        } catch (BadParcelableException e) {
            Log.e("OtpErrorReceiver", e.getLocalizedMessage());
        }
    }
}

Sample app

The WhatsApp OTP Sample App on GitHub demonstrates sending and receiving OTPs via API, integrating both button types, creating templates, and starting a sample server.