# Authy Push Authentications

> \[!WARNING]
>
> As of November 2022, Twilio no longer provides support for Authy SMS/Voice-only customers. Customers who were also using Authy TOTP or Push prior to March 1, 2023 are still supported. The Authy API is now closed to new customers and will be fully deprecated in the future.
>
> For new development, we encourage you to use the [Verify v2 API](/docs/verify/api).
>
> Existing customers will not be impacted at this time until Authy API has reached End of Life. For more information about migration, see [Migrating from Authy to Verify for SMS](https://www.twilio.com/blog/migrate-authy-to-verify).

Before sending a One-Time Password:

1. **Create an Authy Application** ([see Applications documentation](/docs/authy/api/applications))
2. **Create a User** ([see Users documentation](/docs/authy/api/users))

Push authentication offers seamless user experience for second-factor and passwordless authentication and offers the highest level of [cryptographic security](https://www.twilio.com/blog/what-is-public-key-cryptography). All requests are fully encrypted, end to end and allow for non-repudiated transactions.

For users with the ability to install an app on their mobile device or computer, these `ApprovalRequests` can be sent and verified through our REST API. For information on other channels such as SMS or soft tokens, see the Authy API [One-time Passwords documentation](/docs/authy/api/one-time-passwords).

## Create an Approval Request

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 Mobile app(s), Desktop app(s), and any SDK-driven apps. Only the subject of the transaction is sent through Google or Apple push channels. If push notifications fail or delay, the user can still retrieve pending transactions by opening the Authy app or an SDK app manually.

```bash
POST https://api.authy.com/onetouch/{FORMAT}/users/{AUTHY_ID}/approval_requests
```

### URL

| Name      | Type    | Description                                                                                                                |
| :-------- | :------ | :------------------------------------------------------------------------------------------------------------------------- |
| FORMAT    | String  | The format to expect back from the REST API call. `json`, or `xml`.                                                        |
| AUTHY\_ID | Integer | The Authy ID of the user to send a Push Authentication. Create an Authy ID by [registering a user](/docs/authy/api/users). |

### Parameters \[#create-approval-request-parameters]

| Name                                                                                    | Description                                                                                                                                                                                                                                                                                                                                 |
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `message`  String                                                                       | Shown to the user when the push notification arrives. ([📇 PII](/docs/glossary/what-is-personally-identifiable-information-pii#pii-fields) )                                                                                                                                                                                                |
| `details`  Hash (optional) (Max 20 characters for the Key in the key value pair)        | Dictionary containing any `ApprovalRequest` details you'd like to present to the user to assist their decision to approve or deny a transaction. We automatically add a timestamp to transactions. See below for an example on how to use `details`. ([📇 PII](/docs/glossary/what-is-personally-identifiable-information-pii#pii-fields) ) |
| `hidden_details`  Hash (optional) (Max 20 characters for the Key in the key value pair) | Dictionary containing the approval request details hidden to user. This information will be preserved in transaction records but not presented to the user, so it may be useful for your business logic and routing. ([📇 PII](/docs/glossary/what-is-personally-identifiable-information-pii#pii-fields) )                                 |
| `logos`  Hash (optional)                                                                | A dictionary containing override logos that will be shown to user in the push authentication transaction details. By default, we send the logos uploaded through the console. ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) )                                                         |
| `seconds_to_expire`   Integer (optional)                                                | The number of seconds a transaction is valid without user response (pending) before expiring. Defaults to `86400` (one day); `0` will never expire. This should not be set too low as users need time to evaluate a request. ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) )          |

### Response \[#create-approval-request-response]

| Name                     | Description                                                                                                                                                                                                                                                 |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `approval_request`  Hash | Hash containing the keys & values for the `ApprovalRequest`. ([📇 PII](/docs/glossary/what-is-personally-identifiable-information-pii#pii-fields) )                                                                                                         |
| `uuid`  String           | Unique transaction ID of the `ApprovalRequest`. You'll need the `uuid` to query the request status or tie future callbacks to this `ApprovalRequest`. ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) ) |
| `created_at`  Datetime   | The date and time that we created the `ApprovalRequest`. ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) )                                                                                              |
| `status`  String         | Tracks the current state of the `ApprovalRequest` between `pending` a user response, `approved`, `denied`, or `expired`. ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) )                              |

Send Push Authentication

```py
# Download the SDK from https://github.com/twilio/authy-python
from authy.api import AuthyApiClient

# Your API key from twilio.com/console/authy/applications
# DANGER! This is insecure. See https://twil.io/secure
authy_api = AuthyApiClient('api_key')

details = {
    'username': 'Bill Smith',
    'location': 'California, USA',
    'Account Number': '981266321'
}

hidden_details = {
    'transaction_num': 'TR139872562346'
}

logos = [
    dict(res='default', url='https://example.com/logos/default.png'), 
    dict(res='low', url='https://example.com/logos/low.png')
]

response = authy_api.one_touch.send_request(
    authy_id,
    "Login requested for a CapTrade Bank account.",
    seconds_to_expire=120,
    details=details,
    hidden_details=hidden_details,
    logos=logos)

if response.ok():
    print(response.get_uuid())
else:
    print(response.errors())
```

```cs
using System;
using System.Net.Http;
using System.Collections.Generic;


class Program
{
    static void Main(string[] args)
    {
        // Your API key from twilio.com/console/authy/applications
        // DANGER! This is insecure. See https://twil.io/secure
        var AuthyAPIKey = "your_api_key";

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("X-Authy-API-Key", AuthyAPIKey);

            var requestContent = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string, string>("message", "Login requested for a CapTrade Bank account."),
                new KeyValuePair<string, string>("details[username]", "Bill Smith"),
                new KeyValuePair<string, string>("details[username]", "California, USA"),
                new KeyValuePair<string, string>("details[username]", "981266321"),
                new KeyValuePair<string, string>("hidden_details[transaction_num]", "TR139872562346")
            });

            var authy_id = 1234;

            HttpResponseMessage response = client.PostAsync(
                $"https://api.authy.com/onetouch/json/users/{authy_id}/approval_requests",
                requestContent).Result;

            HttpContent responseContent = response.Content;
            Console.WriteLine(responseContent.ReadAsStringAsync().Result);
        }
    }
}
```

```java
// Install the Authy Java SDK from github.com/twilio/authy-java

import com.authy.AuthyApiClient;
import com.authy.api.*;

public class Example {
    // Your API key from twilio.com/console/authy/applications
    // DANGER! This is insecure. See https://twil.io/secure
    public static final String API_KEY = "your_api_key";

    public static void main(String[] args) {
        AuthyApiClient client = new AuthyApiClient(API_KEY);

        String message = "Login requested for a CapTrade Bank account.";

        ApprovalRequestParams approvalRequestParams = new ApprovalRequestParams.Builder(authyId, message)
                .addDetail("username", "Bill Smith")
                .addDetail("location", "California, USA")
                .addDetail("Account Number", "981266321")
                .addHiddenDetail("transaction_num", "TR139872562346")
                .addLogo(ApprovalRequestParams.Resolution.Default, "https://example.com/logos/default.png")
                .build();

        OneTouchResponse response = client.getOneTouch().sendApprovalRequest(approvalRequestParams);

        if (response.isOk()) {
            String uuid = response.getApprovalRequest().getUUID();
            System.out.println(uuid);
        } else {
            System.out.println(response.getError());
        }
    }
}
```

```php
<?php

// Download the SDK from https://github.com/twilio/authy-php
// Update the path below to your autoload.php,
// see https://getcomposer.org/doc/01-basic-usage.md
require_once '/path/to/vendor/autoload.php';

// Your API key from twilio.com/console/authy/applications
// DANGER! This is insecure. See https://twil.io/secure
$authy_api = new Authy\AuthyApi('api_key');

$options = array(
    "details[username]" => "Bill Smith",
    "details[location]" => "California, USA",
    "details[Account Number" => "981266321",
    "hidden_details[transaction_num]" => "TR139872562346"
);

$request = $authy_api->createApprovalRequest(
    $authy_id,
    "Login requested for a CapTrade Bank account.",
    $options);

if ($request->ok()) {
    printf($request->bodyvar("approval_request")->uuid);
}
```

```rb
# Download the SDK from https://github.com/twilio/authy-ruby
require 'authy'

# Your API key from twilio.com/console/authy/applications
# DANGER! This is insecure. See https://twil.io/secure
Authy.api_key = 'your_api_key'
Authy.api_uri = 'https://api.authy.com'

response = Authy::OneTouch.send_approval_request(
  id: authy_id,
  message: "Login requested for a CapTrade Bank account.",
  details: {
    'username': 'Bill Smith',
    'location': 'California, USA',
    'Account Number': '981266321'
  },
  hidden_details: {
    'transaction_num': 'TR139872562346'
  }
)

puts response.approval_request['uuid']
```

```bash
curl "https://api.authy.com/onetouch/json/users/123/approval_requests" \
  -H "X-Authy-API-Key: d57d919d11e6b221c9bf6f7c882028f9" \
  --data-urlencode message="Login requested for a CapTrade Bank account." \
  --data-urlencode details[username]="Bill Smith" \
  --data-urlencode details[location]="California, USA" \
  --data-urlencode details[Account Number]="981266321" \
  --data-urlencode hidden_details[transaction_num]="TR139872562346" \
  --data-urlencode seconds_to_expire=120 \
  --data-urlencode logos[][res]="default" \
  --data-urlencode logos[][url]="https://example.com/logos/default.png" \
  --data-urlencode logos[][res]="low" \
  --data-urlencode logos[][url]="https://example.com/logos/low.png"
```

```json
{
  "approval_request": {
    "uuid": "c31f7620-9726-0135-6e6f-0ad8af7cead6"
  },
  "success": true
}
```

This request generates a push notification that looks like this:

![Authy push request for CapTrade Bank login with approve and deny options.](https://docs-resources.prod.twilio.com/e726913fb62f4f2669d120b72a79dff603fccca01d81c9b0c3b04171b09189ef.png)

### Use a Custom Logo in an Approval Request

By default, all the `ApprovalRequest`s created will be shown to the user using the logo defined in your [application in the console](https://www.twilio.com/login?g=%2Fconsole%2Fauthy%2Fapplications%3F\&t=a4acba3fc18d14c66ef33cde9ba121b6e7832c6431ee26a3f3c01bfe83271ab4). However, you can provide a custom image at the time of the request.

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`.

Options for the `res` field are:

| `default` | fallback logo if logo for device resolution is not provided |
| --------- | ----------------------------------------------------------- |
| `low`     | for devices with low resolution                             |
| `med`     | for devices with medium resolution                          |
| `high`    | for devices with high resolution                            |

> \[!NOTE]
>
> All image URLs must be served over HTTPS and not HTTP. Due to mobile platform restrictions, image requests must be over a secure channel.

## Check Approval Request Status

There are two ways for you to check on `ApprovalRequest` status. You can poll the endpoint below for the status of an `ApprovalRequest` or you can use a webhook callback. Polling is the quickest way to get started using and testing the endpoint.

In order to implement polling, you can hit the following endpoint repeatedly until the status changes. We suggest polling once per second for the best user experience.

```bash
GET https://api.authy.com/onetouch/{FORMAT}/approval_requests/{PUSH_UUID}
```

### URL

| Name             | Description                                                                                                                                                                       |
| :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FORMAT` String  | The format to expect back from the REST API call. `json` or `xml`.                                                                                                                |
| `PUSH_UUID` UUID | The approval request ID. (Obtained from the response to an ApprovalRequest) ([🏢 not PII](/docs/glossary/what-is-personally-identifiable-information-pii#fields-marked-not-pii) ) |

### Response

| Name                      | Description                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `approval_request`   Hash | Hash containing the status of the approval request and other attributes as you can see in the example below. Possible values of nested `status` key are `pending`, `expired`, `approved`, or `denied`. "device" key only included in response when status is `approved` or `denied`. ([📇 PII](/docs/glossary/what-is-personally-identifiable-information-pii#pii-fields) ) |

Check status of push authentication request

```py
# Download the SDK from https://github.com/twilio/authy-python
from authy.api import AuthyApiClient

# Your API key from twilio.com/console/authy/applications
# DANGER! This is insecure. See https://twil.io/secure
authy_api = AuthyApiClient('api_key')

status = authy_api.one_touch.get_approval_status('c31f7620-9726-0135-6e6f-0ad8af7cead6')

print(status.content)
```

```cs
using System;
using System.Net.Http;
using System.Collections.Generic;


class Program
{

    static void Main(string[] args)
    {
        // Your API key from twilio.com/console/authy/applications
        // DANGER! This is insecure. See https://twil.io/secure
        var AuthyAPIKey = "your_api_key";

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("X-Authy-API-Key", AuthyAPIKey);

            var request_uuid = "c31f7620-9726-0135-6e6f-0ad8af7cead6";

            HttpResponseMessage response = client.GetAsync(
                $"https://api.authy.com/onetouch/json/approval_requests/{request_uuid}").Result;

            HttpContent responseContent = response.Content;
            Console.WriteLine(responseContent.ReadAsStringAsync().Result);
        }
    }
}
```

```java
// Install the Authy Java SDK from github.com/twilio/authy-java

import com.authy.AuthyApiClient;
import com.authy.api.*;

public class Example {
    // Your API key from twilio.com/console/authy/applications
    // DANGER! This is insecure. See https://twil.io/secure
    public static final String API_KEY = "your_api_key";

    public static void main(String[] args) {
        AuthyApiClient client = new AuthyApiClient(API_KEY);

        OneTouchResponse response = client.getOneTouch().getApprovalRequestStatus("c31f7620-9726-0135-6e6f-0ad8af7cead6");

        if (response.isOk()) {
            System.out.println(response.getApprovalRequest().getStatus());
        } else {
            System.out.println(response.getError());
        }
    }
}
```

```php
<?php

// Download the SDK from https://github.com/twilio/authy-php
// Update the path below to your autoload.php,
// see https://getcomposer.org/doc/01-basic-usage.md
require_once '/path/to/vendor/autoload.php';

// Your API key from twilio.com/console/authy/applications
// DANGER! This is insecure. See https://twil.io/secure
$authy_api = new Authy\AuthyApi('api_key');

$uuid = "c31f7620-9726-0135-6e6f-0ad8af7cead6";

$request = $authy_api->getApprovalRequest($uuid);

if ($request->ok()) {
    printf($request->bodyvar("approval_request")->status);
}
```

```rb
# Download the SDK from https://github.com/twilio/authy-ruby
require 'authy'

# Your API key from twilio.com/console/authy/applications
# DANGER! This is insecure. See https://twil.io/secure
Authy.api_key = 'your_api_key'
Authy.api_uri = 'https://api.authy.com'

response = Authy::OneTouch.approval_request_status(:uuid => 'c31f7620-9726-0135-6e6f-0ad8af7cead6')

puts response.approval_request['status']
```

```bash
curl -i "https://api.authy.com/onetouch/json/approval_requests/c31f7620-9726-0135-6e6f-0ad8af7cead6" \
    -H "X-Authy-API-Key: d57d919d11e6b221c9bf6f7c882028f9"
```

```json
{
  "success": true, 
  "approval_request": {
    "status": "approved", 
    "_user_email": "user@example.com", 
    "uuid": "c31f7620-9726-0135-6e6f-0ad8af7cead6", 
    "notified": false, 
    "hidden_details": {
      "transaction_num": "TR139872562346"
    }, 
    "created_at": "2019-09-03T23:34:53Z", 
    "app_id": "5c1234c1234cfd6e8b1234", 
    "_app_serial_id": 123456, 
    "updated_at": "2019-09-03T23:37:01Z", 
    "seconds_to_expire": 120, 
    "_app_name": "Example Authy Application", 
    "processed_at": "2019-09-03T23:37:01Z", 
    "user_id": "59f27bc1234ef64e34a61234", 
    "_id": "5d6e12344d79f51234b6", 
    "_authy_id": 123,
    "device": {
      "city":"San Francisco",
      "country":"United States",
      "ip":"192.168.92.226",
      "region":"California",
      "registration_city":"New York",
      "registration_country":"United States",
      "registration_ip":"127.0.0.4",
      "registration_method":"push",
      "registration_region":"New York",
      "os_type":"ios",
      "last_account_recovery_at":null,
      "id":2456245,
      "registration_date":1506380735,
      "last_sync_date":1508436616,
      "enabled_unlock_methods": "pin, fingerprint",
      "last_unlock_method_used": "pin",
      "last_unlock_date": 1540601752
    }
  }
}
```

### Push Authentication Callbacks

In your final application, we recommend exposing a URL to Twilio and using [webhooks](/docs/glossary/what-is-a-webhook). With a webhook, we will call your URL immediately when a user reacts to an `ApprovalRequest`. Webhooks are a more scalable solution than polling. For redundancy you can implement both webhook callbacks and long-polling.

Learn more about [how to validate incoming Twilio Authy API requests](/docs/authy/validation) and [how to implement Authy Webhooks](/docs/authy/api/webhooks). You can set a callback URL in the Push Authentication tab of your Authy Application in the [console](https://www.twilio.com/login?g=%2Fconsole%2Fauthy%2Fapplications%3F\&t=a4acba3fc18d14c66ef33cde9ba121b6e7832c6431ee26a3f3c01bfe83271ab4).

![Authy push authentication settings with webhook URL input and HTTP POST option highlighted.](https://docs-resources.prod.twilio.com/4515fa75727018f0280cade705ec4b36b8799526e84d2bc41bee1276921e71e7.png)
