Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Transactional Time-based One Time Passwords


Use this feature if you need to tie a one-time password with transaction data. It's specifically useful to comply with PSD2 Dynamic Linking(link takes you to an external page) to fulfill Strong Customer Authentication Requirement.

To enable this feature you need to enable it in your Application's settings in the Twilio Console(link takes you to an external page):

console enable transactional totp.

Once this is enabled, end users will have the option to Scan a QR code from your application view in the Authy App.

Scan transactional TOTP QR code.
(information)

Info

This feature is only supported in the following versions of the Authy App. End users will have to update their mobile applications to the following versions:

  • iOS 22.3+
  • Android 23.7+

Create a Transactional QR code

create-a-transactional-qr-code page anchor

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


_10
txotp://totp?message=msg&details[key1]=value1&hidden_details[key1]=value1

message, details, and hidden_details are 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.

Parameters should be URL encoded.

Parameters

create-transactional-qr-code-parameters page anchor
NameDescription
message StringShort description about the transaction
details HashDictionary containing any details related to the transaction you want the end user to see.
hidden_details Hash (optional)Dictionary containing any details related to the transaction you don't necessary want the end user to see.

Example transaction string

example-transaction-string page anchor

_10
txotp://totp?message=Approve+money+transaction&details[Amount]=1000+Euros&details[To]=John+Doe&details[Destination+Account]=29385&details[Source+Account]=98381&details[Reason]=transfer+money&hidden_details[Transaction+ID]=T2293

(information)

Info

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

generate-the-qr-code-from-the-transaction-string page anchor

Note: we do not recommend storing the QR code since it can potentially leak sensitive data. Instead, we recommend:

  1. Sending the QR code as a base64 encoded image in your HTML
  2. Generating the QR code from your application with a library like github.com/skip2/go-qrcode(link takes you to an external page)

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.

example transactional totp qr code.

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.


Verify a Transactional One-Time Password

verify-a-transactional-one-time-password page anchor

To verify a transactional one-time password, pass in the user provided token, the user authy_id and the transaction message, details and hidden_details. Twilio will use HTTP status codes for the response.


_10
GET https://api.authy.com/protected/{FORMAT}/verify/{TOKEN}/{AUTHY_ID}

NameDescription
FORMAT StringThe format to expect back from the REST API call. json or xml.
TOKEN IntegerThe 6-8 digit transactional TOTP you are verifying.
AUTHY_ID StringThe Authy ID for the user validating the token.
NameDescription
message StringShort description about the transaction
details HashDictionary containing any details related to the transaction you want the end user to see.
hidden_details Hash (optional)Dictionary containing any details related to the transaction you don't necessary want the end user to see.
CodeMessage
200"Token is valid." Until you successfully verify a token for a new user, this will return 200 (see Note)*.
401"Token is invalid." Invalid token. If you wish to verify the token anyway, pass force=true (see Note)*.
401"The param details can not have empty values." For example a request with ?details[Name]=&details[Surname]=Doe will fail.
401"The param hidden details can not have empty values." For example a request with ?hidden_details[ID]=&hidden_details[Account]=690239 will fail.
NameDescription
token StringEither "is valid" or "is invalid" (🏢 not PII)
success String"true" if the code was valid. Please note this field is a String and not a Boolean. (🏢 not PII)
device ObjectAn object including some details about the device used to get or generate the token. The fields included in the device object are: city, region, country, ip, registration_city, registration_region, registration_country, registration_ip, registration_date, os_type, last_account_recovery_at and id. (📇 PII)
(warning)

Warning

Every new Authy user must complete a verification before subsequent authentications can be done. Otherwise, see how to force verification of unregistered users here.

Verify Transactional TOTP

verify-transactional-totp page anchor
Python
C#
Java
PHP
curl

_23
# Download the helper library from https://github.com/twilio/authy-python
_23
from authy.api import AuthyApiClient
_23
_23
# Your API key from twilio.com/console/authy/applications
_23
# DANGER! This is insecure. See http://twil.io/secure
_23
authy_api = AuthyApiClient('api_key')
_23
_23
options = {
_23
"message": "Approve money transaction",
_23
"details[Amount]": "1000 Euros",
_23
"details[To]": "John Doe",
_23
"details[Destination Account]": 29385,
_23
"details[Source Account]": 98381,
_23
"details[Reason]": "transfer money",
_23
"hidden_details[Transaction ID]": "T2293"
_23
}
_23
_23
verification = authy_api.tokens.verify(
_23
authy_id,
_23
token=1685105,
_23
options=options)
_23
_23
print(verification.ok())

Output

_21
{
_21
"message":"Token is valid.",
_21
"token":"is valid",
_21
"success":"true",
_21
"device":{
_21
"city":"Brooklyn",
_21
"country":"United States",
_21
"ip":"192.168.0.1",
_21
"region":"New York",
_21
"registration_city":"Medellín",
_21
"registration_country":"Colombia",
_21
"registration_ip":"192.168.0.3",
_21
"registration_method":"sms",
_21
"registration_region":"Antioquia",
_21
"os_type":"ios",
_21
"last_account_recovery_at":1498837117,
_21
"id":4854321,
_21
"registration_date":1551300946,
_21
"last_sync_date":1551301762
_21
}
_21
}

An invalid token will return the following error message:


_10
{
_10
"message":"Token is invalid",
_10
"token":"is invalid",
_10
"success":false,
_10
"errors":{
_10
"message":"Token is invalid"
_10
},
_10
"error_code":"60020"
_10
}


Rate this page: