Magic link
Passwordless sign-in via a one-time link delivered by email. Links are 15-minute, single-use, and wipe on consumption.
Copy this quickstart guide as a prompt for LLMs to implement KolayLogin in your application.
Prereqs
- Enable in instance config:
authConfig.magic_link = true(dashboard → auth methods). - Configure Resend (
KL_RESEND_API_KEY+KL_EMAIL_FROM) so the email actually delivers.
Flow
┌───────── client ─────────┐ ┌──────── KolayLogin ───────┐
│ POST /sign-in/magic-link │ ───▶ │ store tokenHash, send mail │
│ │ │ │
│ user clicks link │ ◀── │ email { verifyUrl } │
│ GET /magic-link/verify │ ───▶ │ exchange token → cookies │
└──────────────────────────┘ └────────────────────────────┘Send the link
curl -X POST $KL_API/v1/auth/sign-in/magic-link \
-H 'content-type: application/json' \
-d '{"email":"ada@example.com"}'The API returns { ok: true } regardless of whether the email is registered (user enumeration defense).
Complete the flow
The email contains a URL like /v1/auth/magic-link/verify?token=.... When clicked, the API sets the session cookies and responds with the created user/session ids. Your app should land on the magic-link handler route and then redirect to the dashboard.
app/magic-link/page.tsx (Next.js handler)
export default async function MagicLinkRedirect({
searchParams,
}: { searchParams: Promise<{ token?: string }> }) {
const { token } = await searchParams;
if (!token) return <p>Invalid link.</p>;
const res = await fetch(
`${"https://api.kolaylogin.com"}/v1/auth/magic-link/verify?token=${encodeURIComponent(token)}`,
{ credentials: 'include', cache: 'no-store' },
);
if (!res.ok) return <p>Link expired.</p>;
return <meta httpEquiv="refresh" content="0;url=/dashboard" />;
}Errors
401 magic_link_disabled— feature off on the instance.401 invalid_token— token consumed, expired, or never issued.