PHP
VerifySpeed PHP Client Library Documentation
The VerifySpeed PHP client library lets you manage verifications from your backend. It supports message-based methods (WhatsApp Message, Telegram Message), OTP methods (WhatsApp OTP, Telegram OTP, SMS OTP), OTP validation, and local verification token decryption.
Please read Verification Flow and Verification Methods to understand the verification process.
Setup
Package information
| Composer package | verifyspeed/vs-php (GitHub) |
| Description | Official PHP backend SDK for VerifySpeed API |
| Current version | 2.1.0 |
| License | MIT |
| Namespace | VerifySpeed\ |
Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.1 |
| Guzzle | ^7.9 |
| libphonenumber-for-php | ^8.13 |
PHP extension json | required |
PHP extension openssl | required (token decryption) |
Step 1: Install the Package
composer require verifyspeed/vs-php
To pin a specific release:
composer require verifyspeed/vs-php:^2.1
Composer installs Guzzle for HTTP requests, libphonenumber-for-php to validate and normalize phone numbers for OTP methods, and uses the openssl extension for verification token decryption.
Step 2: Configure the Server Key
Set your server key once before calling any API methods. You can obtain the key from the dashboard.
<?php
use VerifySpeed\VerifySpeed;
VerifySpeed::setServerKey('YOUR_SERVER_KEY');
Usage
Creating a Verification
Call VerifySpeed::createVerification() with the method name. For OTP methods, you must also pass a phone number; VerifySpeed sends a one-time password to that number.
createVerification parameters
| Parameter | Required | Description |
|---|---|---|
$methodName | Yes | Verification method identifier (e.g., telegram-message, whatsapp-otp). |
$language | No | Language for the verification flow (e.g., en, ar, ckb). |
$phoneNumber | For OTP methods | User's phone number. Required when $methodName is whatsapp-otp, telegram-otp, or sms-otp. The library validates and normalizes the number to E.164 format before sending the request. Omit for message-based methods. |
If $methodName is an OTP type and $phoneNumber is omitted or empty, the client throws InvalidArgumentException with the message Phone number is required for OTP verification methods (whatsapp-otp, telegram-otp, sms-otp).
/**
* Creates a verification.
*
* @param string $methodName Verification method identifier (e.g., "whatsapp-message", "whatsapp-otp").
* @param string|null $language Optional language (e.g., "en", "ar", "ckb").
* @param string|null $phoneNumber User phone number. Required for OTP methods; normalized to E.164.
* VerifySpeed sends a one-time password to this number. Omit for message-based methods.
* @return VerificationResult
*
* @throws \InvalidArgumentException When required arguments are missing or invalid.
* @throws \RuntimeException When the server key is not set or the API request fails.
*/
VerifySpeed::createVerification(
string $methodName,
?string $language = null,
?string $phoneNumber = null
): VerificationResult;
Message-based method
For message-based methods (whatsapp-message, telegram-message), omit $phoneNumber. The response includes a deep link for the client app.
<?php
use VerifySpeed\VerifySpeed;
VerifySpeed::setServerKey('YOUR_SERVER_KEY');
try {
$result = VerifySpeed::createVerification(
methodName: 'telegram-message',
language: 'ar'
);
echo "Method: {$result->getMethodName()}\n";
echo "Verification Key: {$result->getVerificationKey()}\n";
echo "Deep Link: {$result->getDeepLink()}\n";
// Return verificationKey and deepLink to your mobile/web app.
} catch (\InvalidArgumentException $e) {
echo "Invalid input: {$e->getMessage()}\n";
} catch (\RuntimeException $e) {
echo "Request failed: {$e->getMessage()}\n";
}
OTP-based method
For OTP methods (whatsapp-otp, telegram-otp, sms-otp), pass $phoneNumber. VerifySpeed sends the OTP to that number. Your app collects the code from the user and sends it to your backend; your backend calls validateOtp() (see below).
<?php
use VerifySpeed\VerifySpeed;
VerifySpeed::setServerKey('YOUR_SERVER_KEY');
try {
$result = VerifySpeed::createVerification(
methodName: 'whatsapp-otp',
language: 'en',
phoneNumber: '+14255552673'
);
echo "Verification Key: {$result->getVerificationKey()}\n";
// getDeepLink() is null for OTP methods — return verificationKey to your client app.
} catch (\InvalidArgumentException $e) {
echo "Invalid input: {$e->getMessage()}\n";
} catch (\RuntimeException $e) {
echo "Request failed: {$e->getMessage()}\n";
}
Validating OTP
After creating an OTP verification, call VerifySpeed::validateOtp() from your backend with the code the user entered and the verificationKey from createVerification(). See Validating OTP for the REST contract.
validateOtp parameters
| Parameter | Required | Description |
|---|---|---|
$code | Yes | OTP code entered by the user (max 5 characters). |
$verificationKey | Yes | verificationKey from createVerification() for the same OTP session. |
/**
* Validates an OTP code for a verification session.
*
* @param string $code OTP code entered by the user (max 5 characters).
* @param string $verificationKey Verification key from createVerification().
* @return ValidateOtpResult
*
* @throws \InvalidArgumentException When code or verification key is missing or invalid.
* @throws \RuntimeException When the server key is not set or the API request fails.
*/
VerifySpeed::validateOtp(
string $code,
string $verificationKey
): ValidateOtpResult;
Example
<?php
use VerifySpeed\VerifySpeed;
use VerifySpeed\EncryptionTool;
VerifySpeed::setServerKey('YOUR_SERVER_KEY');
try {
$result = VerifySpeed::validateOtp(
code: '12345',
verificationKey: 'YOUR_VERIFICATION_KEY'
);
if ($result->getSucceed()) {
echo "Phone: {$result->getPhoneNumber()}\n";
echo "Token: {$result->getToken()}\n";
// Optional: decrypt token for methodName, dateOfVerification, verificationKey
$decrypted = EncryptionTool::decryptToken(
$result->getToken(),
VerifySpeed::getServerKey()
);
echo "Method: {$decrypted->getMethodName()}\n";
echo "Verified at: {$decrypted->getDateOfVerification()->format(\DateTimeInterface::ATOM)}\n";
} else {
echo "Error: {$result->getErrorMessage()} ({$result->getErrorCode()})\n";
}
} catch (\InvalidArgumentException $e) {
echo "Invalid input: {$e->getMessage()}\n";
} catch (\RuntimeException $e) {
echo "Request failed: {$e->getMessage()}\n";
}
When getSucceed() is false, check getErrorCode() and getErrorMessage(). Known API error codes:
errorCode | Description |
|---|---|
OTP_EXPIRED | The OTP session has expired. |
OTP_INVALID | The provided code does not match. |
OTP_ALREADY_VERIFIED | This verification was already completed. |
Verifying Tokens
Use EncryptionTool to decrypt verification tokens (from validateOtp(), the mobile SDK, or other flows). Tokens expire after 5 minutes; expired tokens throw InvalidArgumentException.
/**
* Verifies and decrypts a verification token (alias of decryptToken).
*
* @throws \InvalidArgumentException When the token is invalid, corrupted, or expired
* @throws \RuntimeException When decryption fails
*/
EncryptionTool::verifyVerificationToken(string $token, string $serverKey): DecryptTokenResult;
/**
* Decrypts a verification token.
*
* @throws \InvalidArgumentException When the token is invalid, corrupted, or expired
* @throws \RuntimeException When decryption fails
*/
EncryptionTool::decryptToken(string $token, string $serverKey): DecryptTokenResult;
<?php
use VerifySpeed\EncryptionTool;
try {
$result = EncryptionTool::decryptToken('YOUR_VERIFICATION_TOKEN', 'YOUR_SERVER_KEY');
echo $result->getPhoneNumber() . "\n";
echo $result->getMethodName() . "\n";
echo $result->getVerificationKey() . "\n";
echo $result->getDateOfVerification()->format(\DateTimeInterface::ATOM) . "\n";
} catch (\InvalidArgumentException $e) {
echo "Token invalid or expired: {$e->getMessage()}\n";
} catch (\RuntimeException $e) {
echo "Decryption failed: {$e->getMessage()}\n";
}
On success, validateOtp() already returns phoneNumber. Use EncryptionTool when you also need methodName, dateOfVerification, or verificationKey from the token without calling the verification result API. For more examples, see Verification Result Documentation.
Models
VerificationResult
Returned by createVerification(). Contains the verification key and, for message-based methods, a deep link.
| Method | Description |
|---|---|
getMethodName() | The verification method used (e.g., whatsapp-otp). |
getVerificationKey() | Key that identifies this verification; pass to your client app or validateOtp(). |
getDeepLink() | URL for deep-link verification. null for OTP methods. |
toArray() | Associative array with methodName, verificationKey, and deepLink. |
deepLinkis set for message-based methods (whatsapp-message,telegram-message).deepLinkisnullfor OTP methods (whatsapp-otp,telegram-otp,sms-otp).
ValidateOtpResult
Returned by validateOtp().
| Method | Description |
|---|---|
getSucceed() | true when the OTP is valid for the given verificationKey. |
getToken() | Verification token when getSucceed() is true; otherwise null. |
getPhoneNumber() | Verified phone number in E.164 when getSucceed() is true; otherwise null. |
getErrorMessage() | Human-readable error when getSucceed() is false; otherwise null. |
getErrorCode() | Machine-readable error code when getSucceed() is false; otherwise null. |
toArray() | Associative array with succeed, token, phoneNumber, errorMessage, and errorCode. |
DecryptTokenResult
Returned by EncryptionTool::decryptToken() and EncryptionTool::verifyVerificationToken().
| Method | Description |
|---|---|
getPhoneNumber() | Verified phone number in E.164 format. |
getDateOfVerification() | DateTimeImmutable when verification completed (UTC). |
getMethodName() | Verification method used (e.g., whatsapp-otp). |
getVerificationKey() | Key that identifies the verification session. |
toArray() | Associative array with phoneNumber, dateOfVerification, methodName, and verificationKey. |
Exceptions
| Exception | When thrown |
|---|---|
\InvalidArgumentException | Empty or invalid arguments for createVerification() or validateOtp(); missing phone number for OTP methods; invalid phone number format; invalid, corrupted, or expired verification token in EncryptionTool. |
\RuntimeException | Server key not set (setServerKey not called); non-success HTTP response; network or deserialization errors; decryption failure in EncryptionTool. |
Phone number validation
For OTP methods, the library uses libphonenumber to parse and validate $phoneNumber and formats it as E.164 before calling the API. Invalid numbers throw InvalidArgumentException with a message such as Invalid phone number format. Please use E.164 format (e.g., +1234567890).
API Example (Laravel)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use VerifySpeed\EncryptionTool;
use VerifySpeed\VerifySpeed;
class VerificationController extends Controller
{
public function __construct()
{
VerifySpeed::setServerKey(config('services.verifyspeed.server_key'));
}
public function create(Request $request)
{
$request->validate([
'methodName' => 'required|string',
'phoneNumber' => 'nullable|string',
'language' => 'nullable|string',
]);
try {
$verification = VerifySpeed::createVerification(
methodName: $request->input('methodName'),
language: $request->input('language'),
phoneNumber: $request->input('phoneNumber')
);
return response()->json($verification->toArray());
} catch (\InvalidArgumentException $e) {
return response()->json(['error' => $e->getMessage()], 400);
} catch (\RuntimeException $e) {
return response()->json(['error' => $e->getMessage()], 502);
}
}
public function validateOtp(Request $request)
{
$request->validate([
'code' => 'required|string|max:5',
'verificationKey' => 'required|string',
]);
try {
$result = VerifySpeed::validateOtp(
code: $request->input('code'),
verificationKey: $request->input('verificationKey')
);
if (!$result->getSucceed()) {
return response()->json($result->toArray(), 422);
}
return response()->json($result->toArray());
} catch (\InvalidArgumentException $e) {
return response()->json(['error' => $e->getMessage()], 400);
} catch (\RuntimeException $e) {
return response()->json(['error' => $e->getMessage()], 502);
}
}
public function decryptToken(Request $request)
{
$request->validate(['token' => 'required|string']);
try {
$result = EncryptionTool::decryptToken(
$request->input('token'),
config('services.verifyspeed.server_key')
);
return response()->json($result->toArray());
} catch (\InvalidArgumentException $e) {
return response()->json(['error' => $e->getMessage()], 400);
} catch (\RuntimeException $e) {
return response()->json(['error' => $e->getMessage()], 502);
}
}
}
License
This package is distributed under the MIT License. Copyright VerifySpeed ([email protected]).