Authy OneTouch API

Quick overview

Authy OneTouch uses a very simple API consisting of two endpoints. One for creating approval requests and another to check the status of the approval request. To simplify the process of handling a request, you can set a callback URL in the Authy dashboard. When a user responds to the OneTouch notification, the Authy API posts data to your callback URL. If you are unable to provide a URL or you would like to simply poll Authy for the status of a request, you can call the ApprovalRequest endpoint.

Authy OneTouch uses a REST API and build off our TOTP API The API is designed to use HTTP response codes to indicate status. The body of the response will also include more information.

The api_key can be obtained by logging into the Authy dashboard and selecting the app for which you are authenticating users

Supported Formats

At the moment we support JSON and XML formats. For convenience and compatibility with old http implementations we only support the POST and GET http verbs. You always need to specify a format (json | xml),

Production API locations

The Authy API server is at:

Demo AngularJS/NodeJS Implementation

You can clone and run our demo app repo which uses polling to implement OneTouch. This full-stack implementation demonstrates both Authy 2FA and Phone Verification.

cURL API Examples

You can also clone our cURL API repo which implements all features of the Authy APIs including creating and checking the status of OneTouch requests. We've included a Postman collection and environment as well.

Create ApprovalRequest

This is the main endpoint. This will create a new approval request for the given Authy ID and send it to the end user along with a push notification to the Authy smartphone application.

If you configured a callback url and the user responds to the notification, the Authy service will make a HTTP request to it with the transaction response.



Name Type Description
message String Required. The message shown to the user when the approval request arrives.
details Hash Dictionary containing the [ApprovalRequest] details that will be shown to user
hidden_details Hash Dictionary containing the approval request details hidden to user.
logos Hash Dictionary containing the logos that will be shown to user.
seconds_to_expire Integer Optional, defaults to 86400 (one day). Number of seconds that the approval request will be available for being responded. If set to 0, the approval request won't expire. Expiration time can be set to several months, without affecting security. For certain use cases, it might be important to set a short expiration time. However, expiration time should not affect security by enforcing users to act too quickly. Instead, the users should be able to take their time to check the details of the approval requests before approving/denying it.


Name Type Description
approval_request Hash Hash containing the UUID of the created approval request.


Creating a new approval request

curl "" \
-d api_key="d57d919d11e6b221c9bf6f7c882028f9" \
-d message="Login requested for a CapTrade Bank account." \
-d details[username]="Bill Smith" \
-d details[location]="California, USA" \
-d details[Account Number]="981266321" \
-d hidden_details[ip_address]='' \
-d seconds_to_expire=120

Sample response


Using a custom logo

By default, all the approval requests created will be shown to the user using the logo defined in your Authy application in the Authy dashboard. However you can provide a customized logo at the time of the request. This is useful if you require an image that is specific to the action.

Make sure ALL your urls for images are HTTPS and not HTTP. Due to iOS and other platform restrictions, requests for images must be made via secure channels.

The logos parameter is expected to be an array of objects, each object with two fields: res (for resolution) and url (the location where you host your logo). If you include the logos parameter, we expect it to include a res with value default. If you don't include it, an error will be returned.

The other options for the res field on the logo are:

  • default (if you don't provide logos for each resolution this will be used instead)
  • low (will be shown on devices with low resolution)
  • med (will be shown on devices with medium resolution)
  • high (will be shown on devices with high resolution)

Creating a new approval request with custom logos.

curl "" \
-d api_key="d57d919d11e6b221c9bf6f7c882028f9" \
-d message="Login requested for a CapTrade Bank account." \
-d details[username]="Bill Smith" \
-d details[location]="California, USA" \
-d details[Account Number]="981266321" \
-d hidden_details[ip_address]='' \
-d seconds_to_expire=120
-d logos[][res]='default' \
-d logos[][url]='' \
-d logos[][res]='low' \
-d logos[][url]=''

Sample response

  "approval_request": {

Check ApprovalRequest status

This call returns the status of the given approval request. This end point doesn't require to sign the request.



Name Type Description
uuid String Required. The approval request ID. (Obtained from the response to an ApprovalRequest)


Name Type Description
approval_request Hash Hash containing the status of the approval request and other attributes as you can see in the example below. If you are using older client api version may the response will differ from the actual sample and only will contain the files describe below.

Only old version of OneTouch

[authy_id, callback_action, uuid, app_name, app_id, created_at, updated_at, seconds_to_expire, status, created_at_time]


curl "" Sample response

  "approval_request": {
    "authy_id": 3,
      "device_uuid": 4,
      "callback_action": "approval_request_status",
      "uuid": "cdbabf40-1c65-0133-d113-34363b620e52",
      "app_name": "OneTouch App",
      "app_id": "581bc86a1245bfb5c0457126",
      "created_at": "Thu, 03 Nov 2016 23:29:46 UTC +00:00",
      "updated_at": "Thu, 03 Nov 2016 23:29:46 UTC +00:00",
      "seconds_to_expire": "86400",
      "expiration_timestamp": "946641599",
      "logos": "",
      "message": "Request to Login",
      "status": "pending",
      "details": { "Email Address": "" },
      "hidden_details": { "ip": "" },
      "created_at_time": "946641599",
      "customer_uuid": "20",
      "signature": "rzqf/n08coE0Vi7IjbzAbt0IYMprJGAUx18kSJWE37K0mhvCGwepkm/pSDXuSs+5kSUFK80L9RT7/BZ7YwojSt5WhPnpRSImm5qKlvsNnGOPYCKVcFJxXCNJhtaztL/2BjOMzdC5yNHH5uJIDGBhlb5fLVErsvauvxXWo/Cj2STfITdSPULFz6XcbM1BDIriW7kP0GkELfUqE1iEuONEdhKYmPGolh3/U4t8i0NYkQSPhbOGG1DZEsxhnxtelyBNOGK9sFojTsAg7dWesRYnyDkjTHZ1MvggdZwXo4qxphrY2Ve7+o04EHPZW9RPvakwl9yQ6rVsspVF/xZT14BsgA=="
    "success": true

Verifying authenticity of callbacks from Authy

"We strongly recommend you verify the authenticity of Authy callbacks to ensure unauthorized 3rd parties can’t forge your users' approval request responses.

To authenticate, Authy sends an HTTP header with an HMAC signature of the full request body in every callback. The HTTP header is called X-Authy-Signature and is signed using your API Key."

The following steps are demonstrated in this NodeJS Gist.

To verify the callback follow these steps:

  • Create a string using the url without params:
url = request.url
# => ""
  • Create a string variable with the HTTP method in upper case (GET, POST):
http_method = request.method
#=> "POST"
  • Sort the list of received parameters in case-sensitive order and convert them to URL format (both key and value should be URL-encoded):
params = request.params
#=> {b: "val|ue&2", a: "value1"}
sorted_params = params.to_param
#=> "a=value1&b=val%7Cue%262"
  • Get the nonce from the http header:
nonce = request.headers["X-Authy-Signature-Nonce"]
#=> 1427849783.886085
  • Join nonce, http_method, url and sorted_params together with the | character:

    NOTE: The string should contain exactly 3 | characters.

data = nonce + "|" + http_method + "|" + url + "|" + sorted_params
#=> "1427849783.886085|POST||a=value1&b=val%7Cue%262"
  • Hash the resulting data using HMAC-SHA256, using your api_key as the key:
digest = hmac_sha256(data, api_key)
  • Encode in base64 the digest:
digest_in_base64 = encode_in_base64(digest)
  • Encode in base64 the digest. Base64 encoding should not contain line feeds. It must be encoded as described in the RFC 4648 (
digest_in_base64 = encode_in_base64(digest)
  • Compare the digest_in_base64 with the http header X-Authy-Signature.
request.headers["X-Authy-Signature"] == digest_in_base64
#=> if true, signature is ok!

Return Codes

The following are the return HTTP codes supported by the Dashboard API.

  • 200: Response is correct.
  • The body of the response will include the data requested.
  • 400: There was an error with the request.
  • The body of the response will have more information.
  • 401: API Key is invalid.
  • Please check your api key.
  • 404: The requested resource was not found.
  • If the device uuid you are sending is not associated to a device,or you are trying to access to a non owned device you may get this error.
  • 503: Many reasons, body will include details:
  • An internal error on Authy OneTouch. Your application is accessing an API call you don't have access too. API usage limit. If you reach API usage limits a 503 will be returned, please wait until you can do the call again.

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.