Two-factor Authentication API

Action Needed For Vonage Customers Using US Shared Short Codes

Effective immediately, Vonage will no longer accept new programs for Shared Short Codes for A2P messaging. T-Mobile and AT&T's new code of conduct prohibits the use of shared originators for A2P (application to person) traffic. Please migrate any existing Shared Short Code traffic to one of our alternative solutions. To help you with this transition, please use the Vonage guide to alternatives. Please contact us to migrate to a new solution.

You can use Two-factor Authentication API to prove a user's identity. Provision a US Short Code with a standard or custom template that specifies the custom parameters for two-factor authentication (2FA) messages. These APIs support 2FA for the US and Canada.

Two-factor authentication (also known as 2FA) provides user identification by combining two different components. In this case, a phone number associated with your user and a PIN. Before you use this API you have to set up a preapproved Short Code for 2FA.

The workflow for Two-factor Authentication API is:

Two-factor Authentication workflow
Two-factor Authentication workflow

  1. Send a 2FA request.
  2. Check the status code in the response and ensure that you sent the request to Vonage correctly.
  3. Vonage delivers your PIN to your user's handset.
  4. Your user enters this PIN into your application.
  5. Receive the delivery receipt at your webhook endpoint.

To ensure that your traffic is send over the best possible route, use Conversion API to tell us about the reliability of your 2FA communication. Adding your conversion data means Vonage delivers your messages faster and more reliably.

Note: Vonage calculates quality of delivery (QoD) statistics using delivery receipts (DLR). In the United States, we only receive intermediate and not handset DLRs. This means Dashboard analytics cannot show QoD statistics for messages sent via the US short code API.

Implementing the Two-factor Authentication API workflow

To use the 2FA API you:

  1. Send a 2FA request.

    var https = require('https');
    
    var data = JSON.stringify({
     api_key: 'API_KEY',
     api_secret: 'API_SECRET',
     to: '441632960960',
     pin: 'A_PIN'
    });
    
    var options = {
     host: 'rest.nexmo.com',
     path: '/sc/us/2fa/json',
     port: 443,
     method: 'POST',
     headers: {
       'Content-Type': 'application/json',
       'Content-Length': Buffer.byteLength(data)
     }
    };
    
    var req = https.request(options);
    
    req.write(data);
    req.end();
    
    var responseData = '';
    req.on('response', function(res){
     res.on('data', function(chunk){
       responseData += chunk;
     });
    
     res.on('end', function(){
       console.log(JSON.parse(responseData));
     });
    });
    <?php
    $url = 'https://rest.nexmo.com/sc/us/2fa/json?' . http_build_query([
            'api_key' => 'API_KEY',
            'api_secret' => 'API_SECRET',
            'to' => '441632960960',
            'pin' => 'A_PIN'
        ]);
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    import urllib
    
    params = {
        'api_key': 'API_KEY',
        'api_secret': 'API_SECRET',
        'to': '441632960960',
        'pin' : 'A_PIN'
    }
    
    url = 'https://rest.nexmo.com/sc/us/2fa/json?' + urllib.urlencode(params)
    
    response = urllib.urlopen(url)
    print response.read()
    require "net/http"
    require "uri"
    
    uri = URI.parse("https://rest.nexmo.com/sc/us/2fa/json")
    params = {
        'api_key' => 'API_KEY',
        'api_secret' => 'API_SECRET',
        'to' => '441632960960',
        'pin' => 'A_PIN'
    }
    
    response = Net::HTTP.post_form(uri, params)
    
    puts response.body
  2. Check the status code in the response and ensure that you sent the request to Vonage correctly.

    // Decode the json object you retrieved when you ran the request.
    
    var decodedResponse = JSON.parse(responseData);
    
    console.log('You sent ' + decodedResponse['message-count'] + ' messages.\n');
    
    decodedResponse['messages'].forEach(function(message) {
        if (message['status'] === "0") {
          console.log('Success ' + decodedResponse['message-id']);
        }
        else {
          console.log('Error ' + decodedResponse['status']  + ' ' +  decodedResponse['error-text']);
        }
    });
    <?php
    // Decode the json object you retrieved when you ran the request.
    $decoded_response = json_decode($response, true);
    
    error_log('You sent ' . $decoded_response['message-count'] . ' messages.');
    
    foreach ( $decoded_response['messages'] as $message ) {
        if ($message['status'] == 0) {
            error_log("Success " . $message['message-id']);
        } else {
            error_log("Error {$message['status']} {$message['error-text']}");
        }
    }
    import json
    
    #Using the response object from the request
    
    if response.code == 200 :
        data = response.read()
        #Decode JSON response from UTF-8
        decoded_response = json.loads(data.decode('utf-8'))
        # Check if your messages are successful
        messages = decoded_response["messages"]
        for message in messages:
            if message["status"] == "0":
                print "success"
    else :
        #Check the errors
        print "unexpected http {code} response from nexmo api". response.code
    require 'json'
    
    # Decode the json object from the response object you retrieved from the request.
    if response.kind_of? Net::HTTPOK
      decoded_response = JSON.parse(response.body )
    
      messagecount = decoded_response["message-count"]
    
      decoded_response["messages"].each do |message|
        if message["status"] == "0"
            p "message " + message["message-id"] + " sent successfully.\n"
          else
            p "message has error " + message["status"]  + " " + message["error-text"]
        end
      end
    else
      puts response.code + " error sending message"
    end
  3. Vonage delivers your PIN to your user's handset.

  4. Your user enters this PIN into your application.

  5. Receive the delivery receipt at your webhook endpoint so you can see:

Note: remember to return a status code when you receive the delivery receipt.