Two Factor Authentication (WhatsApp)
Generate, send, and verify a WhatsApp one-time password using an Authentication Message Template, a code generator, and a Sender. For developers building a WhatsApp-based 2FA flow.
Use WhatsApp to create a two-factor authentication (2FA) flow that generates, sends, and verifies a one-time password (OTP).
Prerequisites
Complete these steps before you start:
- Copy your API Key from the Communications Platform: Preferences > API.
- Get a Facebook Business Manager ID.
- Create a WhatsApp Business Account ID (WABA).
- Create a Sender.
You will create the WhatsApp Authentication Message Template in the first step.
Workflow
- Create a WhatsApp Authentication Message Template.
- Create a code generator.
- Send a verification code to the recipient.
- Check the verification code status and validate the code.
1. Create a WhatsApp Authentication Message Template
Create an authentication message template with an OTP button.
The authentication message template includes:
- Fixed preset text:
- META defines the Body message:
"<VERIFICATION_CODE> is your verification code". - Optionally include META's security recommendation:
“For your security, do not share this code”. - Optionally add a Footer expiration warning:
"This code expires in <NUM_MINUTES> minutes".
- META defines the Body message:
- OTP button: Add an OTP button. A copy-code button copies the one-time password to the recipient's clipboard.
Use the following example:

NOTEThe
"982012"code displayed in the example will differ from the one sent to the end user because the next step is to generate that code. Additionally, the codes are generated randomly.
HTTP Request: POST /whatsapp/templates
Provide either the WhatsApp Business Account ID (WABA) or the unique identifier of the Sender in this request.
WARNINGEnter only one of the required parameters (
“wabaId”or“senderId”), not both.In this example we are going to enter the WABA Id.
The request body includes a Body, Footer, and OTP button.
{
"name": "elipackage_authentication",
"category": "AUTHENTICATION",
"templateLanguages": [
{
"language": "en",
"components": [
{
"type": "BODY",
"securityRecomendation": true
},
{
"type": "FOOTER",
"expirationMinutes": 15
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "OTP",
"otp_type": "COPY_CODE",
"text": "Copy Code"
}
]
}
]
}
]
}Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
| name | Yes | Name of the message template. The name of each message template you create cannot be the same. |
| category | Yes | Type of message template. Message Template category.
|
| templateLanguages | Yes | Array of languages objects containing the language that message template may be rendered in and the components. |
| templateLanguages. language |
Yes | Language of the message template. Currently the API supports 3 Languages: English, Spanish and Portuguese. Required if you want to send message templates in languages other than English. English: Spanish: Portuguese: |
| templateLanguages. components |
Yes | The parts of the message template. Array of components objects containing the different types of options you can include in the message. |
| templateLanguages. components. type |
Yes | Type of component of the message template you want to send. There are three optional main message template components you can include in the message template:
|
| templateLanguages. components. securityRecomendation |
No | Only applies to the Set |
| templateLanguages. components. expirationMinutes |
No | Only applies to the Indicates the number of minutes the password or code is valid. If omitted, the code expiration warning will not be displayed in the delivered message. Minimum |
| templateLanguages. components. buttons |
Yes | Only applies to the Array of Buttons type options you can include to the message template. |
| templateLanguages. components. buttons. type |
Yes | Only applies to the Buttons Type option. The buttons object contains the following option:
|
| templateLanguages. components. buttons. otp_type |
Yes | Only applies to the Set the |
| templateLanguages. components. buttons. text |
Yes | Only applies to the Copy code button text. Maximum 25 characters. |
{
"meta": {
"timestamp": 1707177081141,
"transactionId": "395b2ac9-1046"
},
"errors": {
"reason": "error Meta message template",
"details": {}
},
"data": {
"wabaId": 11234567232528,
"name": "elipackage_authentication",
"category": "AUTHENTICATION",
"templateLanguages": [
{
"id": "37587656784131",
"language": "en",
"components": [
{
"type": "BODY",
"securityRecomendation": true
},
{
"type": "FOOTER",
"expirationMinutes": 15
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "OTP",
"otp_type": "COPY_CODE",
"text": "Copy Code"
}
]
}
]
}
]
}
}- Run the request in your terminal.
- Copy the WhatsApp Authentication Message Template ID from
data.templateLanguages.idin the response body.
2. Create a Code Generator
After META approves the WhatsApp Authentication Message Template, create a code generator. A code generator creates the numeric verification code that you send through WhatsApp when a user signs up or logs in.
Use the following request body to configure the code generator:
HTTP Request: POST /v1/2fa
{
"codeLength": 6,
"expirationMinutes": 15,
"channels": [
{
"type": "WHATSAPP",
"address": "584111111111",
"templateId": "3752812345987345",
"placeholder": "code"
}
]
}Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
| codeLength | Yes | Security code length. The security codes used for two-factor authentication are a minimum of 6 digits. |
| expirationMinutes | Yes | Security code expiration time in minutes. |
| channels | Yes | Contains the information of the channels to be used for the code delivery. Only ONE channel can be chosen when generating a code. |
| channels. type |
Yes | Define the channel from where the code will be sent. Currently supports independent channels for 2FA: For this example we set the |
| channels. address |
Yes | Phone number of the sender. Phone number provided during the WABA account setup will be used as the sender of the notification message. Only accepts numeric characters. Do not include the "+" sign.> type. |
| channels. templateId |
Yes | Unique identifier of the WhatsApp Authentication Message Template. |
| channels. placeholder |
Yes | The Body message (defined by META) contains a placeholder ( |
{
"meta": {
"timestamp": 1707180413315,
"transactionId": "a6a16b0a-b830"
},
"data": {
"id": 250,
"codeLength": 6,
"expirationMinutes": 15,
"channels": [
{
"placeholder": "code",
"address": "584111111111",
"templateId": "3752812345987345",
"type": "WHATSAPP"
}
]
}
}- Run the request in your terminal.
- Copy the code generator ID from
data.idin the response body.
3. Send a Verification Code
Send a verification code to the recipient through WhatsApp.
HTTP Request: POST /v1/2fa/{id}/codes
Replace <CODE_GENERATOR_ID> with the data.id value returned when you created the code generator.
{
"channel": "WHATSAPP",
"receiver": "+525500000000"
}Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
| channel | Yes | Define the channel from where the code will be sent. Currently supports independent channels for 2FA: For this example we set the |
| receiver | Yes | Determines the destination phone number for your authentication message template and verification code. Numbers are specified in E.164 format → (‘+’ and a country code). |
{
"meta": {
"timestamp": 1707183277726,
"transactionId": "7942859d-45d2"
},
"data": {
"requestId": "c12345616-fee2-f345hgf-fgh123"
}
}- Run the request in your terminal.
- Copy the 2FA request ID from
data.requestIdin the response body.
4. Check and Validate the Verification Code
After the recipient receives the code, use this endpoint to check its status, verify the code, or cancel the request. This example checks the code status and then verifies the code.
HTTP Request: PATCH /v1/2fa/{id}/codes
Replace <CODE_GENERATOR_ID> with the code generator ID and <REQUEST_ID> with the 2FA request ID. Check the verification code status before you validate it.
{
"action": "status",
"requestId": "<REQUEST_ID>"
}Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
| action | Yes | Apply one the following actions to the verification code:
For this example, we set the |
| requestId | Yes | Unique identifier of the two factor authentication request. That is, this is the ID of the verification code that has to be verified. |
{
"meta": {
"timestamp": 1707243156412,
"transactionId": "6ae15fa5-1e97"
},
"data": {
"id": 534,
"userID": "+525500000000",
"token": "151820",
"requestID": "c12345616-fee2-f345hgf-fgh123",
"expirationDate": "2024-02-06T01:44:37.020949",
"validationDate": null,
"validationChannel": "WHATSAPP",
"status": "PENDING"
}
}Response Body Parameters
| Parameter | Description |
|---|---|
| data | Unique identifier of the status API call. |
| data. userID |
Destination phone number for your authentication message template and verification code. Numbers are specified in E.164 format → (‘+’ and a country code). |
| data. token |
Verification code that was sent to the end user. |
| data. expirationDate |
Date at which the verification code will expire and no longer be valid for authentication. |
| data. validationDate |
Date on which the verification code has been valid. |
| data. validationChannel |
Channel from where the verification code was sent. |
| data. status |
Status of the verification code.
|
- Run the request in your terminal.
- Confirm that
data.statusis“PENDING”before verifying the code. - Use the verification code from
data.tokenin the next request.
Because the verification code is in “PENDING” status, you can now validate it.
NOTEIn this API Call, the user needs to enter their verification code to valid the code.
We acquired that code from the previous request to provide you with a clearer understanding of its status and validation.
{
"action": "verify",
"requestId": "c12345616-fee2-f345hgf-fgh123",
"code": "151820"
}Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
| action | Yes | Apply one the following actions to the verification code:
For this example, we set the |
| requestId | Yes | Unique identifier of the two factor authentication request. That is, this is the ID of the verification code that has to be verified. |
| code | Yes | Verification code that has to be verified. |
{
"meta": {
"timestamp": 1707252519688,
"transactionId": "424cd21f-a190",
"explain": "valid code"
}
}Response Body Parameters
| Parameter | Description |
|---|---|
| explain | Valid verification code. |
Updated 2 days ago
