# Authy API

> \[!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).

With the Twilio Authy API, you can add a second factor of authentication or passwordless logins to your web application. It supports OTP sent via voice and SMS, TOTP generated in the free [Authy app](https://authy.com) (or any compatible [authenticator app](/docs/authy/api/one-time-passwords#authenticator-app-generated-time-based-one-time-passwords) like Google Authenticator) and push authentication via the free [Authy app](https://authy.com). To start working with the API, first create an application in the Console and get the API Key.

## API Base URL

All URLs in the reference documentation use the following base URL:

```bash
https://api.authy.com
```

All requests to the Authy REST API are served over HTTPS. Unencrypted HTTP is not supported.

## Authy API Keys

All `HTTP` requests to the Authy REST API `/protected` endpoints are protected with an API Secret you pass as an HTTP header `X-Authy-API-Key`, e.g.:

```bash
curl 'https://api.authy.com/protected/json/app/details' \
-H "X-Authy-API-Key: $AUTHY_API_KEY"
```

The API Key can be found in the [Authy section of the Twilio Console](https://www.twilio.com/console/authy/applications/) after clicking through to your Authy application.

![General settings showing application name 'NewApp' and obscured production API key.](https://docs-resources.prod.twilio.com/3c314d088d85b7d9b017ca7cfb94f78ef617659cecb9cf6f60168546724d56bc.png)

### Supported Formats

The Authy API currently supports **JSON** and **XML** formats. When making API calls, you will need to specify `json` or `xml` format.

## Authy Workflow

This guide shows the three steps to completing a basic two-factor verification via SMS. Follow the links for more documentation on advanced features such as sending [Push Authentications](/docs/authy/api/push-authentications), [registering users without needing their phone number or email](/docs/authy/api/users#add-a-user-without-providing-email-or-phone-number), [PSD2 compliance](/docs/authy/api/transactional-time-based-one-time-passwords), and more.

First, create an Authy Application in the Twilio Console and grab the API Key as demonstrated above.

Step 1: Create an Authy User

```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')

user = authy_api.users.create(
    email='new_user@example.com',
    phone='405-342-5699',
    country_code=57)

if user.ok():
    print user.id
    # user.id is the `authy_id` needed for future requests
else:
	print user.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>("user[email]", "new_user@example.com"),
                new KeyValuePair<string, string>("user[cellphone]", "405-342-5699"),
                new KeyValuePair<string, string>("user[country_code]", "1"),
            });

            HttpResponseMessage response = client.PostAsync(
                "https://api.authy.com/protected/json/users/new",
                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);

        Users users = client.getUsers();
        User user = users.createUser(
                "new_user@example.com",
                "405-342-5699",
                "57");

        if (user.isOk()) {
            System.out.println(user.getId());
        } else {
            System.out.println(user.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');

$user = $authy_api->registerUser('new_user@example.com', '405-342-5699', 57); // email, cellphone, country_code

if($user->ok()) {
    printf($user->id());
} else {
    foreach($user->errors() as $field => $message) {
        printf("$field = $message\n");
    }
}
```

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

authy = Authy::API.register_user(:email => 'new_user@example.com', :cellphone => "405-342-5699", :country_code => "57")

if authy.ok?
  puts authy.id
else
  puts authy.errors
end
```

```bash
curl -XPOST "https://api.authy.com/protected/json/users/new" \
-H "X-Authy-API-Key: d57d919d11e6b221c9bf6f7c882028f9" \
--data-urlencode 'user[email]=user@domain.com' \
--data-urlencode 'user[cellphone]=317-338-9302' \
--data-urlencode 'user[country_code]=54'
```

```json
{
  "message": "User created successfully.",
  "user": {
    "id": 123
  },
  "success": true
}
```

An Authy Application is the set of common configurations used to create and check one-time passcodes and manage push authentications. This includes features like:

* Application Name (used in the one-time password message templates)
* Token Length
* ...and more

One application can be used to send multiple tokens, it is not necessary to create a new application each time.

[Authy Users documentation.](/docs/authy/api/users)

Step 2: Send an SMS with a One-Time Password

```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')

sms = authy_api.users.request_sms(authy_id)

if sms.ok():
    print sms.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 authy_id = 1234;

            HttpResponseMessage response = client.GetAsync(
                $"https://api.authy.com/protected/json/sms/{authy_id}").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);

        Users users = client.getUsers();
        Hash response = users.requestSms(authyId);

        if (response.isOk()) {
            System.out.println(response.getMessage());
        } 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');

$sms = $authy_api->requestSms($authy_id);

if ($sms->ok()) {
    printf($sms->message());
} else {
    print_r($sms->errors());
}
```

```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::API.request_sms(:id => authy_id)

puts response.message
```

```bash
# create a user first to get their Authy ID
# https://www.twilio.com/docs/authy/api/users

curl -i "https://api.authy.com/protected/json/sms/{AUTHY_ID}" \
    -H "X-Authy-API-Key: d57d919d11e6b221c9bf6f7c882028f9"
```

```json
{
    "success":true,
    "message":"SMS token was sent",
    "cellphone":"+1-XXX-XXX-XX02"
}
```

This will send a token to the end user through the specified channel. Supported channels are `sms` or `call`.

If the user has the Authy App, by default, the API will not send the 2FA code via SMS or voice. Instead, a push notification will go to the device, prompting the user to start their app to get the code. You can [override this behavior](/docs/authy/api/one-time-passwords#code-send-a-one-time-password-via-sms-forced).

[One-time Password documentation.](/docs/authy/api/one-time-passwords)

Step 3: Verify the Token

```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')

verification = authy_api.tokens.verify(authy_id, token='1234567')
print(verification.ok())
```

```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 authy_id = 1234;
            var token = 1234567;

            HttpResponseMessage response = client.GetAsync(
                $"https://api.authy.com/protected/json/verify/{token}/{authy_id}").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);

        Tokens tokens = client.getTokens();
        Token response = tokens.verify(authyId, "1297431");

        if (response.isOk()) {
            System.out.println(response.toMap());
        } 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');

$token_entered_by_user = '1234567';
$verification = $authy_api->verifyToken($authy_id, $token_entered_by_user);

if ($verification->ok()) {
    // correct token
}
```

```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::API.verify(:id => authy_id, :token => '1234567')

if response.ok?
  # correct token
else
  # incorrect token
end
```

```bash
curl -i "https://api.authy.com/protected/json/verify/{TOKEN}/{AUTHY_ID}" \
    -H "X-Authy-API-Key: d57d919d11e6b221c9bf6f7c882028f9"
```

```json
{
  "message": "Token is valid.",
  "token": "is valid",
  "success": "true",
  "device": {
    "city": "San Francisco",
    "country": "United States",
    "ip": "97.20.126.156",
    "region": "California",
    "registration_city": "San Francisco",
    "registration_country": "United States",
    "registration_device_id": 456456,
    "registration_ip": "97.34.234.11",
    "registration_method": "push",
    "registration_region": "California",
    "os_type": "android",
    "last_account_recovery_at": null,
    "id": 83372911,
    "registration_date": 1490996931
  }
}
```

This will check whether the user-provided token is correct. The first time you verify a user you will need to [force verification](/docs/authy/api/one-time-passwords#force-one-time-password-validation-for-unregistered-user) to complete the user registration process.

| **Token** | **Success in response** | **Message in response** |
| --------- | ----------------------- | ----------------------- |
| Correct   | `true`                  | `Token is valid.`       |
| Incorrect | `false`                 | `Token is invalid`      |

[One-time Password documentation.](/docs/authy/api/one-time-passwords)

## Authy SDKs

We maintain SDKs to abstract these API calls for all of our standard web languages.

* [PHP Authy SDK](https://github.com/twilio/authy-php)
* [Python Authy SDK](https://github.com/twilio/authy-python)
* [Java Authy SDK](https://github.com/twilio/authy-java)
* [Ruby Authy SDK](https://github.com/twilio/authy-ruby)
