Build the future of communications.
Start building for free

How to use Authy for Offline, Transaction Specific, PSD2 Compliant Authentication


One of the best features about using Soft Tokens or Time-based One Time Passwords (TOTP) for authentication is that they are available offline. The European Payment Services Directive (PSD2) regulation requires Strong Customer Authentication (SCA) for all transactions over €30 by September 2019. Part of the regulation requires that SCA ties transaction-specific information to the authentication, called Dynamic Linking.

This post will show you how to use a new feature of the Authy API and application to implement a compliant offline solution for your application. For more detail on PSD2, SCA, and dynamic linking, check out this post. You can also build SCA with push authorization or SMS, which we show in this blog post.

Getting Started

To code along with this post, you’ll need:

To use the Transactional TOTP feature you need to enable it in your Application's settings in the Twilio Console. Make sure to hit "Save" at the bottom of the settings page:

console enable transactional totp

Next, add yourself as a user to the Authy Application. Select Users from the navigation and then a modal will prompt for email, country code, and cellphone. Make sure to use the same phone number you have connected to your Authy mobile application account.

This will trigger a notification from Authy notifying that the application has been added to your account. I named my Application "Example Transactional TOTP". If you named your Application something different, that will show up in the notification.

Go into your Authy App and find your Application. You should see a "Scan" button in the top right corner. If you don't have that button make sure:

  • You're using the latest version of the Authy App
  • You enabled Transactional TOTP from the console (see above) and restarted your app

Create a Transactional QR code

Now we need to create the QR code a user can scan for a given transaction. This is what allows us to tie transaction-specific information to an authentication event even when the device is offline.

First, create a transaction string with the following format. This will be encoded in the QR code.

# transaction string *format* example

message, details, and hidden_details will be mixed with a seed to generate a unique TOTP. The same exact parameters are required to successfully verify the token. Order of parameters is not important but details will be displayed in the same order they are sent.

Here's an example of a transaction string for transferring €1000 to John Doe:


The recommended length for a transaction string is under 300 characters. It is not recommended to exceed 600 characters. Longer transaction strings create more complicated QR codes and cause slower scanning, especially in older smartphones. This example's length is 228 characters.

Generate the QR Code from the transaction string

We recommend generating the QR code from your application with a library like go-qrcode. For testing, you can use an online generator like

After the QR code is generated display it so your user can scan it with the Authy App. Here is a sample QR code generated from the example transaction string.

Your QR code may not look exactly like the example above when you recreate it. Test if the example works by scanning your QR code with the Authy app on your smartphone. You should see the payment details on the screen like in the screenshot below.

Scan transactional TOTP QR code

Verify a Transactional One-Time Password

To verify a transactional one-time password, grab your application's production API Key and your user's Authy ID from the Twilio Console. The API Key is located in Settings and the Authy ID is found in Users.

Pass in the user provided token, the user authy_id and the transaction message, details and hidden_details. Copy  the following cURL command and paste it in the command line. Replace the {{TOKEN}}, {{AUTHY_ID}}, and {{AUTHY_API_KEY}} with the respective values.

export TOKEN=yourtoken
export AUTHY_ID=yourauthyid
export AUTHY_API_KEY=yourapikey

curl -X GET --globoff "$TOKEN/$AUTHY_ID?message=Approve+money+transaction&details[To]=John+Doe&details[Amount]=1000+Euros&details[Destination+Account]=29385&details[Source+Account]=98381&details[Reason]=transfer+money&hidden_details[Transaction+ID]=T2293&hidden_details[Transaction+ID]=T2293&details[Source+Account]=98381&details[Destination+Account]=29385" -H "X-Authy-API-Key: $AUTHY_API_KEY"

A correct token will generate a response like:

    "message": "Token is valid.",
    "token": "is valid",
    "success": "true",
    "device": {
        "city": "New York",
        "country": "United States",
        "ip": "",
        "region": "New York",
        "registration_city": "San Francisco",
        "registration_country": "United States",
        "registration_ip": "",
        "registration_method": "sms",
        "registration_region": "California",
        "os_type": "ios",
        "last_account_recovery_at": null,
        "id": 12345,
        "registration_date": 1540576334,
        "last_sync_date": 1554322095

An invalid token will return:

    "message":"Token is invalid",
    "token":"is invalid",
        "message":"Token is invalid"

Nice! This is the first step towards making offline PSD2 compliant authentications. Follow along in one of our quickstarts for an example of building this into your application.

Where to next?

For more details on PSD2 compliance, you can read our explainer on dynamic linking. Check out the documentation for more ways to build PSD2 compliant authorization:

Kelley Robinson is a Developer Evangelist for Twilio's Account Security products. Have you built something to secure your application using the Authy API? Get in touch on Twitter @kelleyrobinson.

Sign up and start building
Not ready yet? Talk to an expert.