Headless identity for React SPAs.
Build 100% custom UI states securely in the browser. Using Authepy's Restricted Keys, you can verify emails directly from your React frontend—no backend proxy required.
The Restricted Key
The most critical rule of frontend development is that you cannot hide secrets in the browser. If you put a Standard Key in your React code, malicious actors will steal it.
Authepy solves this with Restricted Keys (`rk_live_...`). These keys are cryptographically bound to your specific domain names. Even if stolen, our Edge Router instantly rejects any request that doesn't originate from your whitelisted website.
OTP requests matching from any of these Origins will be processed.
The Headless Component
With your Restricted Key safe to expose, you have total control over the React UI. No bulky Authepy dependencies are required.
Use standard useState to manage the form transition, and use the native fetch API to talk directly to Authepy.
import React, { useState } from 'react';
const AUTHEPY_API = 'https://api.authepy.com/api';
const RESTRICTED_API_KEY = 'YOUR_RESTRICTED_KEY_HERE';
export default function SPALogin() {
const [email, setEmail] = useState('');
const [code, setCode] = useState('');
const [requestId, setRequestId] = useState(null);
const [status, setStatus] = useState('idle');
const handleSendOTP = async (e) => {
e.preventDefault();
setStatus('loading');
const response = await fetch(`${AUTHEPY_API}/otp/request`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${RESTRICTED_API_KEY}`
},
body: JSON.stringify({ email })
});
const data = await response.json();
if (data.success) {
setRequestId(data.requestId);
setStatus('verify');
}
};
const handleVerifyOTP = async (e) => {
e.preventDefault();
setStatus('loading');
const response = await fetch(`${AUTHEPY_API}/otp/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${RESTRICTED_API_KEY}`
},
body: JSON.stringify({ requestId, userGuess: code })
});
const data = await response.json();
if (data.success) setStatus('success');
};
// Render Logic (Success, Verify, or Initial form)
if (status === 'success') return Logged in!;
if (status === 'verify') return ( /* OTP Code Input */ );
return ( /* Email Input */ );
} Zero Backend Required
Because Authepy's Edge Router handles the email dispatch and cryptographic verification for you, you don't need to spin up an Express proxy server just to authenticate users on a static S3 or Vercel deployment.
Auto-Fill UX Enabled
By building the form yourself, you can add autoComplete="one-time-code" to your input fields, instantly triggering native iOS/Android code suggestions from the keyboard.
Initialize your frontend.
Stop fighting with bloated frontend authentication SDKs. Generate your Restricted Keys and build a completely custom, headless UI today.