The most reliable SMS, WhatsApp, and Telegram verification platform for your business in Iraq and Kurdistan.
OTPIQ provides a simple and powerful Laravel package to send verification codes and custom messages through multiple channels including SMS, WhatsApp, and Telegram with automatic fallback support.
- 🚀 Multiple Channels: SMS, WhatsApp, Telegram with automatic fallback
- 🔐 Verification Codes: Send OTP codes with ease
- 💬 Custom Messages: Send transactional and marketing messages
- 📱 WhatsApp Templates: Support for WhatsApp Business templates
- 🔄 Auto Fallback: Automatic channel switching for delivery guarantee
- 📊 Delivery Tracking: Real-time SMS delivery status tracking
- 🎯 Custom Sender IDs: Use your own branded sender IDs
- ⚡ Fast & Reliable: Optimized for performance
- 🛡️ Exception Handling: Comprehensive error handling
- PHP 8.1, 8.2, 8.3, or 8.4
- Laravel 10, 11, or 12
Install the package via Composer:
composer require rstacode/otpiqPublish the configuration file:
php artisan vendor:publish --tag=otpiq-configAdd your OTPIQ API key to your .env file:
OTPIQ_API_KEY=sk_live_your_api_key_here
OTPIQ_BASE_URL=https://api.otpiq.com/api/
OTPIQ_TIMEOUT=30You can get your API key from the OTPIQ Dashboard.
Retrieve your project details and remaining credits:
use Rstacode\Otpiq\Facades\Otpiq;
$info = Otpiq::getProjectInfo();
echo $info['projectName'];
echo $info['credit'];Response:
[
'projectName' => 'My SMS Project',
'credit' => 15000
]Send a verification code to a phone number:
use Rstacode\Otpiq\Facades\Otpiq;
$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'verification',
'verificationCode' => '123456',
'provider' => 'whatsapp-sms',
]);
echo $response['smsId'];
echo $response['remainingCredit'];
echo $response['cost'];Response:
[
'message' => 'SMS task created successfully',
'smsId' => 'sms-1234567890abcdef123456',
'remainingCredit' => 14800,
'cost' => 200,
'canCover' => true,
'paymentType' => 'prepaid'
]$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'verification',
'verificationCode' => '123456',
'senderId' => 'MyBrand',
'provider' => 'sms',
]);$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'verification',
'verificationCode' => '123456',
'deliveryReport' => [
'webhookUrl' => 'https://your-app.com/webhooks/sms-status',
'deliveryReportType' => 'all',
'webhookSecret' => 'your_webhook_secret_123',
],
]);Send a custom transactional or marketing message:
use Rstacode\Otpiq\Facades\Otpiq;
$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'custom',
'customMessage' => 'Your order #12345 has been confirmed. Thank you!',
'senderId' => 'MyShop',
'provider' => 'sms',
]);Send a message using a pre-approved WhatsApp template:
use Rstacode\Otpiq\Facades\Otpiq;
$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'whatsapp-template',
'templateName' => 'auth_template',
'whatsappAccountId' => '68c46fecc509cdcec8fb3ef2',
'whatsappPhoneId' => '68da31fb518ac3db3eb0a0f4',
'templateParameters' => [
'body' => [
'1' => '123456',
'2' => '10',
],
],
'provider' => 'whatsapp',
]);Track the delivery status of a sent message:
use Rstacode\Otpiq\Facades\Otpiq;
$status = Otpiq::trackSms('sms-1234567890abcdef123456');
echo $status['status'];
echo $status['lastChannel'];Response:
[
'smsId' => 'sms-1234567890abcdef123456',
'phoneNumber' => '964750123456',
'status' => 'delivered',
'cost' => 200,
'isFinalStatus' => true,
'lastChannel' => 'whatsapp',
'channelFlow' => [
[
'channel' => 'whatsapp',
'tried' => true,
'success' => true,
],
]
]Retrieve all your available sender IDs:
use Rstacode\Otpiq\Facades\Otpiq;
$senderIds = Otpiq::getSenderIds();
foreach ($senderIds['data'] as $sender) {
echo $sender['senderId'];
echo $sender['status'];
echo $sender['pricePerSms']['korekTelecom'];
}Response:
[
'success' => true,
'data' => [
[
'_id' => '507f1f77bcf86cd799439011',
'senderId' => 'OTPIQ',
'status' => 'accepted',
'pricePerSms' => [
'korekTelecom' => 80,
'asiaCell' => 80,
'zainIraq' => 80,
'others' => 100,
]
]
]
]The provider parameter allows you to choose how your message is delivered:
auto- Automatic channel selection (default)whatsapp-sms- Try WhatsApp first, fallback to SMStelegram-sms- Try Telegram first, fallback to SMSwhatsapp-telegram-sms- Try WhatsApp, then Telegram, then SMSsms- SMS onlywhatsapp- WhatsApp onlytelegram- Telegram only
The package provides comprehensive error handling through the OtpiqApiException class:
use Rstacode\Otpiq\Facades\Otpiq;
use Rstacode\Otpiq\Exceptions\OtpiqApiException;
try {
$response = Otpiq::sendSms([
'phoneNumber' => '964750123456',
'smsType' => 'verification',
'verificationCode' => '123456',
]);
} catch (OtpiqApiException $e) {
if ($e->isAuthError()) {
echo 'Invalid API key';
}
if ($e->isCreditError()) {
echo 'Insufficient credit: ' . $e->getRemainingCredit();
echo 'Required credit: ' . $e->getRequiredCredit();
}
if ($e->isRateLimitError()) {
echo 'Rate limit exceeded. Wait ' . $e->getRateLimitWaitMinutes() . ' minutes';
}
if ($e->isTrialModeError()) {
echo 'Account in trial mode';
}
if ($e->isSpendingThresholdError()) {
echo 'Spending threshold exceeded';
}
if ($e->isSenderIdError()) {
echo 'Sender ID not found';
}
if ($e->isValidationError()) {
echo 'Validation error: ' . $e->getFirstError();
}
echo $e->getMessage();
print_r($e->getResponseData());
}isAuthError()- Check if error is authentication relatedisCreditError()- Check if error is due to insufficient creditisRateLimitError()- Check if rate limit was exceededisTrialModeError()- Check if account is in trial modeisSpendingThresholdError()- Check if spending threshold was exceededisSenderIdError()- Check if sender ID is invalidisValidationError()- Check if error is validation relatedgetRemainingCredit()- Get remaining credit balancegetRequiredCredit()- Get required credit for the requestgetRateLimitWaitMinutes()- Get wait time in minutesgetFirstError()- Get first validation error messagegetResponseData()- Get full API response data
You can use the OTPIQ dashboard to test your integration:
- Visit the OTPIQ Dashboard
- Navigate to Messaging → Send SMS
- Build and test your API calls interactively
Send an SMS message.
Parameters:
[
'phoneNumber' => 'string (required)',
'smsType' => 'verification',
'verificationCode' => 'string (required)',
'senderId' => 'string (optional)',
'provider' => 'string (optional)',
'whatsappAccountId' => 'string (optional)',
'whatsappPhoneId' => 'string (optional)',
'templateName' => 'string (optional)',
'deliveryReport' => [
'webhookUrl' => 'string',
'deliveryReportType' => 'all|final',
'webhookSecret' => 'string',
],
][
'phoneNumber' => 'string (required)',
'smsType' => 'custom',
'customMessage' => 'string (required)',
'senderId' => 'string (optional)',
'provider' => 'string (optional)',
'whatsappAccountId' => 'string (optional)',
'whatsappPhoneId' => 'string (optional)',
'templateName' => 'string (optional)',
'deliveryReport' => [
'webhookUrl' => 'string',
'deliveryReportType' => 'all|final',
'webhookSecret' => 'string',
],
][
'phoneNumber' => 'string (required)',
'smsType' => 'whatsapp-template',
'templateName' => 'string (required)',
'whatsappAccountId' => 'string (required)',
'whatsappPhoneId' => 'string (required)',
'templateParameters' => [
'body' => [
'1' => 'string',
'2' => 'string',
],
],
'provider' => 'string (optional)',
'deliveryReport' => [
'webhookUrl' => 'string',
'deliveryReportType' => 'all|final',
'webhookSecret' => 'string',
],
]Get project information and remaining credits.
Returns:
[
'projectName' => 'string',
'credit' => 'integer'
]Track SMS delivery status.
Parameters:
$smsId- The SMS ID returned from sendSms()
Returns:
[
'smsId' => 'string',
'phoneNumber' => 'string',
'status' => 'string',
'cost' => 'integer',
'isFinalStatus' => 'boolean',
'lastChannel' => 'string',
'channelFlow' => 'array'
]Get all available sender IDs.
Returns:
[
'success' => 'boolean',
'data' => [
[
'_id' => 'string',
'senderId' => 'string',
'status' => 'string',
'pricePerSms' => [
'korekTelecom' => 'integer',
'asiaCell' => 'integer',
'zainIraq' => 'integer',
'others' => 'integer',
]
]
]
]- Email: [email protected]
- Issues: GitHub Issues
Contributions are welcome! Please feel free to submit a Pull Request.
The MIT License (MIT). Please see License File for more information.