Verify API Reference

Dive into our full API Reference Documentation and seamlessly integrate 2FA functionalities into your website or application.

Our APIs use HTTP verbs and a RESTful endpoint structure. An access key and secret are used as the API Authorization framework. Request and response payloads are formatted as JSON, using UTF-8 encoding and URL encoded values.

API Endpoint

In order to use Verify APIs, you need to first sign up for free at app.2fa.link

https://api.2fa.link/verify

Credentials

All requests to 2FA.link’s REST API need to be authenticated using HTTP Basic Authentication.

API key/secret pair are credentials you can create and revoke in the admin dashboard. These are typically easier to work with for your projects. You can quickly delete them to revoke access if they are compromised or create mutiple key/secret pairs for different use cases. You can also suspend an API key if neccesary to temporary block access.

API Key API Secret
Username Password

One of the most common mistakes that is made with API keys is to inadvertently check them into public repositories on platforms such as GitHub. From these public repositories, fraudsters can search and steal your API access key and use it to send Spam messages and also drain your account balance. The main takeaway is don’t hard-code your API access key and don’t check it into a public code repository.

HTTP Method

2FA.link only support the POST HTTP methods on various resources.

You can create or query a resource using the HTTP POST method on a resource URI. All you need is to provide the relevant fields in JSON! Here’s a POST request that will create a Verify Request using the 2FA.link API.

Note: All trial accounts are rate-limited at 1 request / second / application (api)

Verify Request

Use this to create a new Verify request, we would attempt to sent it by Push Notification to the user. If user is not registered with our 2FA mobile app, it would fallback to OTP SMS.

curl -X POST "https://API_KEY:API_SECRET@https://api.2fa.link/verify" 
-H "accept: application/json" 
-H "Content-Type: application/json; charset=utf-8" 
-d '{
    "from":"2FA",
    "to":"6598765432",
    "mode":"verify"
}'

$fields = [
    'from' => '2FA',
    'to' => '6598765432',
    'mode' => 'verify'
];
$headers = [
    'Accept: application/json',
    'Content-Type: application/json; charset=utf-8'
];
$url = "https://API_KEY:API_SECRET@api.2fa.link/verify";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);

Request-body (content-type: application/json)
Key Mandatory Accepted Description
mode Yes “verify” Mode of operation
from No
[A-Za-z0-9 ]{2,11}
Sender Name to Display (Default: “2FA.link”)
to Yes
[0-9]{10,15}
Receiver in E.164 Format
length No 6-10 OTP length (applicable for SMS only)
no-otl No 0 or 1 One Time Link for SMS (Default: 0)
no-otp No 0 or 1 One Time Pin for SMS (Default: 0)
channel No “sms” Channel to sent (Default: “push”)
purpose No [A-Za-z0-9 .,$]{10,50} Purpose of this 2FA request to be shown to user
Response-body (Positive)
{
    "errorcode":100,
    "errormsg":"Success",
    "channel":"SMS",
    "request_id":"600EC8DB-FFMRSQGCNG"
}
Response-body (Negative)
{
    "errorcode":207,
    "errormsg":"Incorrect MODE Field Format"
}
Response-body
Key Description
errorcode Error code of Verify request
errormsg Error message of Verify request
channel Verify channel sent
request_id ID for Verify request
Note: If the channel is “SMS”, display an OTP input page to capture user’s input.

 

Verify “Check” Request

Use this API call to verify the OTP (SMS) received. This only apply for Verify request that has not reached Final status (Approve/Decline/Expired).

curl -X POST "https://API_KEY:API_SECRET@https://api.2fa.link/verify" 
-H "accept: application/json" 
-H "Content-Type: application/json; charset=utf-8" 
-d '{
    "request_id":"600EC8DB-FFMRSQGCNG",
    "otp":"123456",
    "mode":"check"
}'

$fields = [
    'request_id' => '600EC8DB-FFMRSQGCNG',
    'otp' => '123456',
    'mode' => 'check'
];
$headers = [
    'Accept: application/json',
    'Content-Type: application/json; charset=utf-8'
];
$url = "https://API_KEY:API_SECRET@api.2fa.link/verify";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);

Request-body (content-type: application/json)
Key Mandatory Accepted Description
mode Yes “check” Mode of operation
request_id Yes
ID of Verify request
otp Yes
[0-9]{6,10}
OTP received via SMS or 2FA mobile app
Response-body (Positive)
{
    "request_id":"600ED8FE-YEQJDVLLQI",
    "from":"2FA",
    "to":"6598765432",
    "status":"Success",
    "statuscode":"600",
    "timestamp_submitted":"2021-01-25T14:43:10+00:00",
    "timestamp_finalized":"2021-01-25T14:43:50+00:00"
}
Response-body (Negative)
{
    "request_id":"600EC8DB-FFMRSQGCNG",
    "status":"Expired",
    "statuscode":"602"
}
Response-body
Key Description
request_id ID for Verify request
from Sender Name
to Receiver
status Status of OTP checking
timestamp_submitted Timestamp of Verify request
timestamp_finalized Timestamp of Final status
Status
statuscode status Description
600 Success One-Time-Pin matched
601 Failed One-Time-Pin do not matched
602 Expired One-Time-Pin expired (3 attempts reached)
603 Not Found Verify request not found
(Over 3 minutes or already reached final status)

Verify “Query” Request

Use this API call to query a “Verify” request.

curl -X POST "https://API_KEY:API_SECRET@https://api.2fa.link/verify" 
-H "accept: application/json" 
-H "Content-Type: application/json; charset=utf-8" 
-d '{
    "request_id":"600EC8DB-FFMRSQGCNG",
    "mode":"query"
}'

$fields = [
    'request_id' => '600EC8DB-FFMRSQGCNG',
    'mode' => 'query'
];
$headers = [
    'Accept: application/json',
    'Content-Type: application/json; charset=utf-8'
];
$url = "https://API_KEY:API_SECRET@api.2fa.link/verify";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);

Request-body (content-type: application/json)
Key Mandatory Accepted Description
mode Yes “query” Mode of operation
request_id Yes
ID of Verify request
Response-body (Positive)
{
    "request_id":"600EC8DB-FFMRSQGCNG",
    "from":"2FA",
    "to":"6598765432",
    "channel":"SMS",
    "app_name":"2FA Portal",
    "status":"Approved",
    "statuscode":"700",
    "msg count":"1",
    "price":"-0.05",
    "timestamp_submitted":"2021-01-25T13:34:19+00:00",
    "timestamp_finalized":"2021-01-25T13:38:01+00:00"
}
Response-body (Negative)
{
    "request_id":"600EC8DB-FFMRSQGC",
    "status":"Not Found",
    "statuscode":"704"
}
Response-body
Key Description
request_id ID for Verify request
from Sender Name
to Receiver
channel Channel used to send Verify request
app_name Application Name
status Status of Verify request
statuscode Status Code
msg_count Messages sent
price Price charged (EURO)
timestamp_submitted Timestamp of Verify request
timestamp_finalized Timestamp of Final status
Status
statuscode status Description
700 Approved User Approved this request
701 Declined User Declined this request
702 Expired (Max duration reached) Verify request expired (3 minutes)
703 Expired (Max tries reached) OTP “check” attempted reached (3 times)
704 Not Found Verify request not found
705 Verify Error Error encountered with Verify request
706 Verify Push Sent Verify sent via Push channel (Pending approval)
707 Verify SMS Sent Verify sent via SMS channel (Pending approval)
708 Verify SMS Delivered Verify OTP SMS delivered (Pending approval)
709 Verify SMS Undelivered Verify OTP SMS undelivered (Pending approval)

Verify “TOTP” Request

Use this API call to make a “Verify TOTP” request.

Note: All T-OTP request are rate-limited at 1 request / second / mobile number

curl -X POST "https://API_KEY:API_SECRET@https://api.2fa.link/verify" 
-H "accept: application/json" 
-H "Content-Type: application/json; charset=utf-8" 
-d '{
    "mode":"verify",
    "channel":"totp",
    "to":"6598765432",
    "totp":"123456"
}'

$fields = [
    'mode' => 'verify',
    'channel' => 'totp',
    'to' => '6598765432',
    'totp' => '123456'
];
$headers = [
    'Accept: application/json',
    'Content-Type: application/json; charset=utf-8'
];
$url = "https://API_KEY:API_SECRET@api.2fa.link/verify";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);

Request-body (content-type: application/json)
Key Mandatory Accepted Description
mode Yes “verify” Mode of operation
channel Yes “totp” Channel as TOTP
to Yes [0-9]{10,15} Receiver in E.164 Format
totp Yes [0-9]{6} TOTP received from user via 2FA mobile app
Response-body (Positive)
{
    "request_id":"602B5ED0-DGGJTSFRBY",
    "to":"6598765432",
    "status":"Success",
    "statuscode":800,
    "timestamp_submitted":"2021-02-16T05:57:36+00:00"
}
Response-body (Negative)
{
    "request_id":"602B5E20-DGMVGJJPUU",
    "to":"6598765432",
    "status":"Fail",
    "statuscode":801,
    "timestamp_submitted":"2021-02-16T05:54:40+00:00"
}
Response-body
Key Description
request_id ID for Verify request
to Receiver
status Status of Verify TOTP request
statuscode Status Code
timestamp_submitted Timestamp of Verify TOTP request
Status
statuscode status Description
800 Success T-OTP matched
801 Fail T-OTP does not match

Callback

A callback would be POST to your provided webhook when the users provide their response via the 2FA mobile app or One-Time-Link (OTL) web-app. This mark the final status of the Verify request. For security, you can whitelist traffic from only our IP address (168.119.166.186). Do note that more sites may be added in the future and you would be informed accordingly.

{
    "request_id":"600E2A82-IKEIOSXRZU",
    "from":"2FA",
    "to":"6598765432",
    "status":"Approved",
    "statuscode":"700",
    "timestamp_submitted":"2021-01-25T02:18:42+00:00",
    "timestamp_finalized":"2021-01-25T02:19:04+00:00",
    "ipaddress":"121.6.57.0"
}
Request-body (content-type: application/json)
Key Description
request_id ID of Verify Request
from Sender Name
to Receiver
status Final Status
timestamp_submitted Timestamp of Verify request
timestamp_finalized Timestamp of Final status
ipaddress IP address of client, last octet is masked for user privacy
Status
statuscode status Description
700 Approved User Approved this request
701 Declined User Declined this request

Error Codes

errorcode errormsg
100 Success
101 Invalid API Key or Secret
102 Invalid Account
103 Rate Limit Reached
104 Insufficient Credit in Account
201 Missing Mandatory Field(s) for Requested Mode
202 Invalid API Key or Secret Format
203 Incorrect TO Field Format
204 Incorrect FROM Field Format
205 Incorrect LENGTH Field Format
206 Incorrect CHANNEL Field Format
207 Incorrect MODE Field Format
208 Incorrect OTP Field Format
209 Both no-otp and no-otl Fields cannot be 1
210 Incorrect TOTP Field Format
211 Incorrect REQUEST_ID Field Format
301 SMS Rejected
401 Temporary Error, Please try again later!