This site uses our own Turalogin for auth. click Get Started to log in yourself. Then grab the prompt or the code and add auth to your app in minutes.
Step through what happens on frontend, backend, and the exact code at each point.
User submits their email on your login page
Sign in to continue
We'll send you a login link
// User submits email → calls your backend
const handleSubmit = async (email: string) => {
await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email }),
});
// Show "check your email" message
};The key principle: tokens never touch the browser. Your backend is the only thing that talks to Turalogin.
User's Browser
Your frontend
Your Backend
2 API calls
Turalogin
Email & verify
User's Email
Login link
You write about 30 lines of backend code. Turalogin handles everything else.
1 // 1. Login endpoint (your backend) 2 export async function POST(req: Request) { 3 const { email } = await req.json(); 4 5 await fetch('https://api.turalogin.com/api/v1/auth/start', { 6 method: 'POST', 7 headers: { 8 'Authorization': `Bearer ${API_KEY}`, 9 'Content-Type': 'application/json', 10 }, 11 body: JSON.stringify({ email, validationUrl }), 12 }); 13 14 return Response.json({ success: true }); 15 } 16 17 // 2. Verify endpoint (your backend) 18 export async function POST(req: Request) { 19 const { sessionId } = await req.json(); 20 21 const res = await fetch('https://api.turalogin.com/api/v1/auth/verify', { 22 method: 'POST', 23 headers: { 24 'Authorization': `Bearer ${API_KEY}`, 25 'Content-Type': 'application/json', 26 }, 27 body: JSON.stringify({ sessionId }), 28 }); 29 30 const { user, token } = await res.json(); 31 // YOU create your own session - Turalogin is done! 32 cookies().set('session', createYourOwnSession(user)); 33 return Response.json({ success: true }); 34 }
Email Deliverability
SPF, DKIM, DMARC configured. No spam folder.
Login Link Generation
Cryptographically secure, single-use tokens.
Link Expiration
15-minute automatic expiry. No stale links.
Rate Limiting
Built-in protection against abuse.
Email Templates
Professional, mobile-friendly emails.
Token Validation
Server-side verification. No browser exposure.
Professional, mobile-friendly emails sent from our trusted domain. Your app name is displayed prominently. Users get both a one-click button and a 6-digit code.
auth@mail.turalogin.com with full SPF/DKIM/DMARC configuration.Here's everything you need to add Turalogin to a Next.js app. The patterns work for any backend.
# Get your API key from the Turalogin dashboard
TURALOGIN_API_KEY=tl_live_xxxxxxxxxxxxx
# Where login links redirect to
LOGIN_VALIDATION_URL=http://localhost:3000/auth/verify1 import { NextResponse } from 'next/server'; 2 3 export async function POST(request: Request) { 4 const { email } = await request.json(); 5 6 const response = await fetch( 7 'https://api.turalogin.com/api/v1/auth/start', 8 { 9 method: 'POST', 10 headers: { 11 'Authorization': `Bearer ${process.env.TURALOGIN_API_KEY}`, 12 'Content-Type': 'application/json', 13 }, 14 body: JSON.stringify({ 15 email, 16 validationUrl: process.env.LOGIN_VALIDATION_URL, 17 }), 18 } 19 ); 20 21 if (!response.ok) { 22 const error = await response.json(); 23 return NextResponse.json(error, { status: response.status }); 24 } 25 26 return NextResponse.json({ 27 success: true, 28 message: 'Check your email for the login link' 29 }); 30 }
1 import { NextResponse } from 'next/server'; 2 import { cookies } from 'next/headers'; 3 4 export async function POST(request: Request) { 5 const { sessionId } = await request.json(); 6 7 const response = await fetch( 8 'https://api.turalogin.com/api/v1/auth/verify', 9 { 10 method: 'POST', 11 headers: { 12 'Authorization': `Bearer ${process.env.TURALOGIN_API_KEY}`, 13 'Content-Type': 'application/json', 14 }, 15 body: JSON.stringify({ sessionId }), 16 } 17 ); 18 19 if (!response.ok) { 20 const error = await response.json(); 21 return NextResponse.json(error, { status: response.status }); 22 } 23 24 const { user, token } = await response.json(); 25 26 // Create YOUR session (you control this!) 27 const cookieStore = await cookies(); 28 cookieStore.set('session', token, { 29 httpOnly: true, 30 secure: process.env.NODE_ENV === 'production', 31 sameSite: 'lax', 32 maxAge: 60 * 60 * 24 * 7, // 7 days 33 }); 34 35 return NextResponse.json({ success: true, user }); 36 }
1 'use client'; 2 import { useState } from 'react'; 3 4 export default function LoginPage() { 5 const [email, setEmail] = useState(''); 6 const [sent, setSent] = useState(false); 7 const [loading, setLoading] = useState(false); 8 9 async function handleSubmit(e: React.FormEvent) { 10 e.preventDefault(); 11 setLoading(true); 12 13 const res = await fetch('/api/auth/login', { 14 method: 'POST', 15 headers: { 'Content-Type': 'application/json' }, 16 body: JSON.stringify({ email }), 17 }); 18 19 if (res.ok) setSent(true); 20 setLoading(false); 21 } 22 23 if (sent) { 24 return ( 25 <div className="text-center p-8"> 26 <h1>Check your email!</h1> 27 <p>We sent a login link to {email}</p> 28 </div> 29 ); 30 } 31 32 return ( 33 <form onSubmit={handleSubmit} className="p-8 max-w-md mx-auto"> 34 <input 35 type="email" 36 value={email} 37 onChange={(e) => setEmail(e.target.value)} 38 placeholder="Enter your email" 39 className="w-full p-3 border rounded" 40 required 41 /> 42 <button 43 type="submit" 44 disabled={loading} 45 className="w-full mt-4 p-3 bg-blue-600 text-white rounded" 46 > 47 {loading ? 'Sending...' : 'Send login link'} 48 </button> 49 </form> 50 ); 51 }
1 'use client'; 2 import { useEffect } from 'react'; 3 import { useSearchParams, useRouter } from 'next/navigation'; 4 5 export default function VerifyPage() { 6 const params = useSearchParams(); 7 const router = useRouter(); 8 9 useEffect(() => { 10 const token = params.get('token'); 11 if (!token) return; 12 13 fetch('/api/auth/verify', { 14 method: 'POST', 15 headers: { 'Content-Type': 'application/json' }, 16 body: JSON.stringify({ sessionId: token }), 17 }) 18 .then((res) => res.json()) 19 .then(() => router.push('/dashboard')) 20 .catch(() => router.push('/login?error=invalid')); 21 }, [params, router]); 22 23 return <div className="p-8 text-center">Signing you in...</div>; 24 }
Copy this prompt to Cursor, ChatGPT, or Claude to scaffold the integration in seconds.
I need to add passwordless email authentication to my app using Turalogin. How it works:
1. When user enters email, my backend calls POST https://api.turalogin.com/api/v1/auth/start with:
- Header: Authorization: Bearer TURALOGIN_API_KEY
- Body: { email, validationUrl: "https://myapp.com/auth/verify" }
2. Turalogin sends a login link email. User clicks it and lands on my validation URL with ?token=xxx
3. My verify page's backend calls POST https://api.turalogin.com/api/v1/auth/verify with:
- Header: Authorization: Bearer TURALOGIN_API_KEY
- Body: { sessionId: token }
4. Turalogin returns { success, token, user: { id, email }, expiresIn }. I create my own session.
Please implement this for my app.