Phone + OTP
Sign users in with their phone number. Koolbase sends a 6-digit verification code via SMS, the user enters it, and a session is issued automatically. Ideal for emerging markets and apps where email isn't the primary identifier.
How it works
- Configure an SMS provider for your project (Twilio, Africa's Talking, or Hubtel).
- The user enters their phone number and you call
sendOtp. Koolbase generates a 6-digit code, stores it SHA-256 hashed in Redis with a 5-minute TTL, and sends it via your provider. - The user enters the code and you call
verifyOtp. Koolbase verifies it, creates the user account on first sign-in, and returns a full session.
Supported SMS providers
Twilio
Global
Africa's Talking
Africa-wide
Hubtel
Ghana
For Ghana traffic specifically, Hubtel typically delivers better and at lower cost than Twilio. Africa's Talking is a strong middle ground for multi-country African deployments. Twilio is the global default and easiest to test with.
Configure your SMS provider
Each project picks one SMS provider. Provider credentials are encrypted and stored per project.
Dashboard UI coming soon
Twilio
curl -X PUT https://api.koolbase.com/v1/projects/{project_id}/sms-config \
-H "Authorization: Bearer YOUR_DASHBOARD_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "twilio",
"credentials": {
"account_sid": "ACxxxxxxxxxxxxxxxx",
"auth_token": "your_auth_token",
"from_number": "+15551234567"
},
"sender_id": "YourApp"
}'Africa's Talking
curl -X PUT https://api.koolbase.com/v1/projects/{project_id}/sms-config \
-H "Authorization: Bearer YOUR_DASHBOARD_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "africas_talking",
"credentials": {
"api_key": "your_api_key",
"username": "your_username"
},
"sender_id": "YourApp"
}'Hubtel
curl -X PUT https://api.koolbase.com/v1/projects/{project_id}/sms-config \
-H "Authorization: Bearer YOUR_DASHBOARD_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "hubtel",
"credentials": {
"client_id": "your_client_id",
"client_secret": "your_client_secret"
},
"sender_id": "YourApp"
}'Send OTP
Send a 6-digit code to a phone number in E.164 format. The returned expiresAt timestamp can power a resend countdown timer.
Flutter
import 'package:koolbase_flutter/koolbase_flutter.dart';
final result = await Koolbase.auth.sendOtp(
phoneNumber: '+233244000000',
);
print('Code expires at: ${result.expiresAt}');React Native
import { Koolbase } from '@techfinityedge/koolbase-react-native';
const result = await Koolbase.auth.sendOtp({
phoneNumber: '+233244000000',
});
console.log('Code expires at:', result.expiresAt);Verify OTP and sign in
Once the user enters the code, verify it. If no user exists with this phone number, Koolbase creates one. The isNewUser flag lets you route first-time users to onboarding.
Flutter
final result = await Koolbase.auth.verifyOtp(
phoneNumber: '+233244000000',
code: '123456',
);
if (result.isNewUser) {
// First time — route to onboarding
} else {
// Returning user — route to home
}
print('Signed in as: ${result.session.user.id}');React Native
const result = await Koolbase.auth.verifyOtp({
phoneNumber: '+233244000000',
code: '123456',
});
if (result.isNewUser) {
navigation.navigate('Onboarding');
} else {
navigation.navigate('Home');
}
console.log('Signed in as:', result.session.user.id);Sessions are issued automatically
Link a phone to an existing account
For users who originally signed up with email or OAuth and want to add phone-based sign-in or 2FA, use linkPhone. The user must already be authenticated and must have requested an OTP for the phone number first.
Flutter
// 1. Send OTP to the phone the user wants to link
await Koolbase.auth.sendOtp(phoneNumber: '+233244000000');
// 2. After user enters code, link it to their account
await Koolbase.auth.linkPhone(
phoneNumber: '+233244000000',
code: '123456',
);
// User can now also sign in via phone+OTPReact Native
await Koolbase.auth.sendOtp({ phoneNumber: '+233244000000' });
await Koolbase.auth.linkPhone({
phoneNumber: '+233244000000',
code: '123456',
});Error handling
Each error condition has a typed exception so you can build clear UX for each case.
Flutter
try {
final result = await Koolbase.auth.verifyOtp(
phoneNumber: phone,
code: code,
);
} on OtpExpiredException {
// Show "Code expired — request a new one"
} on OtpMaxAttemptsException {
// Lock the form, force a fresh send
} on OtpInvalidException {
// "That code is incorrect"
} on OtpRateLimitException {
// "Please wait before requesting another code"
} on InvalidPhoneNumberException {
// Format error — fix and retry
}React Native
import {
Koolbase,
OtpExpiredError,
OtpInvalidError,
OtpMaxAttemptsError,
OtpRateLimitError,
} from '@techfinityedge/koolbase-react-native';
try {
const result = await Koolbase.auth.verifyOtp({
phoneNumber: phone,
code,
});
} catch (e) {
if (e instanceof OtpExpiredError) {
// Code expired
} else if (e instanceof OtpInvalidError) {
// Wrong code
} else if (e instanceof OtpMaxAttemptsError) {
// Too many tries
} else if (e instanceof OtpRateLimitError) {
// Too many requests
}
}Phone number format
All phone numbers must be in E.164 format: a +, country code, and subscriber number with no spaces, dashes, or parentheses. Validation runs both client-side in the SDK and server-side in the API.
Valid
+233244000000 Ghana
+14155551234 United States
+442079460000 United Kingdom
Invalid (will fail SDK validation)
0244000000 — missing country code
+233 244 000 000 — spaces not allowed
+233-244-000000 — dashes not allowedRate limits
To prevent SMS pumping abuse and keep your provider costs down, Koolbase enforces two rate limits:
- Per phone number: 3 OTP requests per 10 minutes.
- Per IP address: 10 OTP requests per hour.
Hitting either limit returns 429 Too Many Requests, surfaced as OtpRateLimitException in Flutter and OtpRateLimitError in React Native.
OTP details
- Length: 6 digits, randomly generated.
- Expiry: 5 minutes from send time.
- Max attempts: 3 incorrect attempts invalidate the code.
- Storage: SHA-256 hashed in Redis — never stored in plaintext.
- Single use: codes are deleted on successful verify.
API reference
| Method | Description |
|---|---|
Koolbase.auth.sendOtp(phoneNumber) | Send a 6-digit code via SMS |
Koolbase.auth.verifyOtp(phoneNumber, code) | Verify the code and sign in or sign up |
Koolbase.auth.linkPhone(phoneNumber, code) | Link a phone number to the current authenticated user |