This guide explains how to configure Hubtel SMS verification for OTP delivery in the Prosperous Data Hub application.
In your backend .env file, add the Hubtel SMS credentials:
# SMS Configuration (Hubtel for OTP delivery)
HUBTEL_SMS_BASE_URL=https://smsc.hubtel.com/v1/messages/send
HUBTEL_SMS_CLIENT_ID=your_actual_client_id
HUBTEL_SMS_CLIENT_SECRET=your_actual_client_secret
HUBTEL_SMS_FROM=Prosperous
| Variable | Description | Example |
|---|---|---|
HUBTEL_SMS_BASE_URL |
Hubtel SMS API endpoint | https://smsc.hubtel.com/v1/messages/send |
HUBTEL_SMS_CLIENT_ID |
Your API Client ID from Hubtel | ABC123XYZ789 |
HUBTEL_SMS_CLIENT_SECRET |
Your API Client Secret (keep secure!) | secret_key_abc123xyz789 |
HUBTEL_SMS_FROM |
Sender ID (appears in SMS) | Prosperous |
For fallback email delivery, also configure Gmail:
SMTP_GMAIL_USER=your-email@gmail.com
SMTP_GMAIL_APP_PASSWORD=your_app_specific_password
SMTP_FROM_NAME=Prosperous Data Hub
Ensure required packages are installed:
cd backend
npm ls axios nodemailer
Required packages:
axios - For HTTP requests to Hubtel APInodemailer - For Gmail fallbackCreate a test script to verify Hubtel connection:
# From backend directory
node -e "
require('dotenv').config();
const env = require('./src/config/env');
console.log('Configuration Check:');
console.log('✓ Base URL:', env.HUBTEL_SMS_BASE_URL);
console.log('✓ Client ID configured:', !!env.HUBTEL_SMS_CLIENT_ID);
console.log('✓ Client Secret configured:', !!env.HUBTEL_SMS_CLIENT_SECRET);
console.log('✓ Sender Name:', env.HUBTEL_SMS_FROM);
"
The application automatically routes OTP requests based on channel:
When user requests OTP on their phone number:
When user requests OTP on their email:
The system accepts multiple Ghana phone formats:
✓ +233201234567
✓ 233201234567
✓ 0201234567
✗ 02012345 (too short)
✗ +1201234567 (wrong country)
Monitor OTP delivery in application logs:
# Look for SMS delivery logs
grep -i "hubtel\|SMS\|OTP" logs/app.log
Log messages indicate:
[otpDelivery] Hubtel SMS sent successfully - Success[otpDelivery] Hubtel SMS failed - Failed with details[otpDelivery] Hubtel SMS error - Network/config errorMonitor Hubtel account for delivery status:
Cause: Missing Hubtel credentials
Solution:
# Verify environment variables are set
echo $HUBTEL_SMS_CLIENT_ID
echo $HUBTEL_SMS_CLIENT_SECRET
echo $HUBTEL_SMS_FROM
Causes:
Solutions:
Cause: Hubtel API unresponsive
Solution:
When deploying to Render:
HUBTEL_SMS_CLIENT_IDHUBTEL_SMS_CLIENT_SECRETHUBTEL_SMS_FROMHUBTEL_SMS_BASE_URL# Verify variables on Render
echo "Checking env vars..."
env | grep HUBTEL_SMS
For Ghana market:
curl -X POST http://localhost:4000/api/auth/otp/request \
-H "Content-Type: application/json" \
-d '{
"purpose": "REGISTER",
"channel": "PHONE",
"target": "+233201234567"
}'
Expected response:
{
"success": true,
"otpSessionId": "uuid-here",
"maskedTarget": "****1234"
}
Check your phone for SMS within seconds.
The application has a built-in fallback system:
Log entries show which method was used:
[otpDelivery] Hubtel SMS sent successfully
-- OR --
[otpDelivery] Hubtel SMS error → falling back to Gmail
-- OR --
[otpDelivery] Both SMS and email failed
HUBTEL_SMS_FROM is approved in Hubtel portalEdit backend/src/modules/auth/otpDelivery.js:
// Change timeout from 15000ms to your preferred value
timeout: 15000, // milliseconds
Edit backend/src/modules/auth/otpDelivery.js:
function buildConfirmationText(code, purpose) {
return `Your Prosperous verification code is ${code}. Valid for 10 minutes.`;
}
Set in .env:
NODE_ENV=production
LOG_LEVEL=info
For any issues, check the logs and refer to this guide’s troubleshooting section.