How to Send OTP in React Native (Expo) — 2026
React Native OTP tutorial using Expo and StartMessaging. Includes secure storage, auto-fill (Android SMS Retriever / iOS keychain), and a Node backend pattern.
StartMessaging Team
Engineering
Expo + React Native is a popular stack for Indian consumer apps. This tutorial wires StartMessaging via a small Node backend, with auto-fill and secure session storage.
Overview
- Backend: Express + StartMessaging.
- App: phone screen → OTP screen.
- Android SMS Retriever for auto-fill.
- Expo SecureStore for the JWT token.
Setup
npx create-expo-app otp-rn
cd otp-rn
npx expo install expo-secure-store expo-otp-input
npm install zustandLogin Screens
// App.tsx
import { useState } from 'react';
import { TextInput, Button, View } from 'react-native';
import { otp } from './src/otpService';
export default function App() {
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
const [requestId, setRequestId] = useState<string|null>(null);
return requestId === null ? (
<View><TextInput value={phone} onChangeText={setPhone} placeholder="+919876543210" />
<Button title="Send OTP" onPress={async () => setRequestId((await otp.send(phone)).requestId)} />
</View>
) : (
<View><TextInput value={code} onChangeText={setCode} keyboardType="number-pad" />
<Button title="Verify" onPress={() => otp.verify(requestId, code)} />
</View>
);
}OTP Service
// src/otpService.ts
const BASE = 'https://your-backend.example.com';
export const otp = {
async send(phoneNumber: string) {
const r = await fetch(`${BASE}/auth/send-otp`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phoneNumber }),
});
return r.json();
},
async verify(requestId: string, otpCode: string) {
const r = await fetch(`${BASE}/auth/verify-otp`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ requestId, otpCode }),
});
return r.json();
},
};OTP Auto-Fill
See our auto-fill guide for the SMS Retriever API setup. The SMS body must end with a Google-defined hash so the OS can attribute it.
Secure Token Storage
import * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('session', token);FAQ
Flutter equivalent in our Flutter guide.
Related Articles
Flutter OTP tutorial using StartMessaging on a Firebase Functions backend. Riverpod state, http client, secure cookie session via Firebase Auth custom token.
Keep TRAI DLT-compliant SMS OTP on the server: React Native and Flutter clients call your API only—never ship SMS gateway keys for OTP SMS API India integrations.
Improve OTP UX with Android SMS Retriever, User Consent API, and iOS one-time code fields. Aligns with TRAI DLT-approved SMS templates and StartMessaging when your backend sends the SMS.
Ready to Send OTPs?
Integrate StartMessaging in 5 minutes. No DLT registration required.