{"_id":"@cometalabs/better-auth-passwordless","_rev":"7-518e8f96da06ed8ed0227db451ee3486","name":"@cometalabs/better-auth-passwordless","dist-tags":{"latest":"0.1.8"},"versions":{"0.1.0":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.0","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.0","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"dist":{"shasum":"7595b77999f4a98fa1dd426bc4e15dae595ee8cb","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.0.tgz","fileCount":16,"integrity":"sha512-2wI8xv1kig9mY6yiXC/Htp7BRKNKan39St01DZg7ibdO1bsAUEFHe+iolo8aNvG7Q5OzC6nSDTHU0wgDgBWjlQ==","signatures":[{"sig":"MEUCIA3SHZXeY+zdyFJDQn0hp5mKtHzu1wKYYz0GwTTSovgWAiEAgAEEbsXUWQhhC9xOpAYi2mqIrxC76V2eRV8IF6H5M6w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47739},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"30e99bdbf512aefa422ef93666b73e62b72a29ed","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"_npmVersion":"11.16.0","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"26.3.0","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.0_1782056871078_0.14544215788532355","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.1","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.1","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"homepage":"https://cometalabs.io","bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"dist":{"shasum":"1d0a274696641f5c50e412afc7ba704615218bd0","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.1.tgz","fileCount":16,"integrity":"sha512-ns6cg6E6Vi3uwaAWATe5raY1Zivu/dMfwDWHycJgSu/lClTKQNM8lybTJLPr1NnYvaBaIY6nXWOy2Sg/eYSW3g==","signatures":[{"sig":"MEQCIGy/TwrPfFzYMwZHDBDvNwuSRq2qDRqw4bfejFvIpr1oAiAWVXdUA5/SL8xdf/Y4I0qioeAfLBh/3AtTmeI5pKI9IQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52955},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"a6391e1bfcfaa03ec3ef301d178992d4bb684a1e","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"repository":{"url":"git+https://github.com/CometaLabs/better-auth-passwordless.git","type":"git"},"_npmVersion":"11.16.0","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"26.3.0","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.1_1782057657826_0.7800101275412834","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.4","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.4","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"homepage":"https://cometalabs.io","bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"dist":{"shasum":"2be96cbd918705571b089930c81b34a3b03d4848","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.4.tgz","fileCount":16,"integrity":"sha512-KQGV//aN/n9aMUia/AqGGO5rTDCIR6Li4GAIO/r/vZcw81gv0YH8MaXTN/1wrHGdfUaezBFBWwu15eDabGSQLA==","signatures":[{"sig":"MEYCIQDLig0JZ8KWmGbogPKboFL6kBVHGKAhcHTcRmghANQfvgIhANGRki6aBw5tpX9ESjIkSiYSt+jXGu0qUDqFyJ9+YKAM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53045},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"761a1eda36cd253d34d86abfb69c3f89d18a94e1","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepare":"husky","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"repository":{"url":"git+https://github.com/CometaLabs/better-auth-passwordless.git","type":"git"},"_npmVersion":"10.8.2","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"20.20.2","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","husky":"^9.1.7","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.4_1782072422432_0.23597610971950878","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.5","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.5","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"homepage":"https://cometalabs.io","bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"dist":{"shasum":"ba36ee1fa17ad77617531e8569e57c663173953c","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.5.tgz","fileCount":16,"integrity":"sha512-yreML2+dOBICF2xRzquoAefbDrvaWs+PY0YRBhPekqcebJHOxB9LKl6E+12+6NA0KmAk66Wd4IVu5xOWX5BcGg==","signatures":[{"sig":"MEYCIQCHwKW8hdCCqj+UVLQel9nEtVtmQm/LpidD+o3iWlMTZwIhAIgyxFcH2vnr9kL0wRakX7ZOKltJTD1Z/px307QYYhQb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56813},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"4155f63df74f3fa7c5665ede4aa10d8fc3a7e52d","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepare":"husky","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"repository":{"url":"git+https://github.com/CometaLabs/better-auth-passwordless.git","type":"git"},"_npmVersion":"10.8.2","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"20.20.2","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","husky":"^9.1.7","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.5_1782073270090_0.9189371066694523","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.6","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.6","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"homepage":"https://cometalabs.io","bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"dist":{"shasum":"778b237e70f016df25500acf7a0f8a0d57720a0d","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.6.tgz","fileCount":16,"integrity":"sha512-gBd68y9Q5IsVaZKsELwGCynCP9Asb+TPFjDU3XGDSpWrab/R6lg1r+tkA+7dSeEUxGW5BSiupOT0O0LUsp6VNQ==","signatures":[{"sig":"MEUCIQDkMDZGsRioGYi1bWIxtBtRU7nnqCUqysBZWx5Rnbq76AIgYX16/BTSaHKtLDMwwRYG88XpF+vFf1p3AAsyqRCswq0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67558},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"5517157e99d09073ad001847f396c2801372d4c4","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepare":"husky","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"repository":{"url":"git+https://github.com/CometaLabs/better-auth-passwordless.git","type":"git"},"_npmVersion":"10.8.2","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"20.20.2","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","husky":"^9.1.7","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.6_1782073948161_0.3460436977379946","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.7","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","_id":"@cometalabs/better-auth-passwordless@0.1.7","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"homepage":"https://cometalabs.io","bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"dist":{"shasum":"140e7e69e7468e5e9e9ad78e83fa2ad5ab581b72","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.7.tgz","fileCount":16,"integrity":"sha512-a/L4j6AEU0X5k5cRmOkpX8GM2lRkmqvYK89pnZ5+0f4AxRS8YlZWjEM0xb+qsya1nGbbihBmkrO1+iUHUJpFEg==","signatures":[{"sig":"MEUCIQDbMVbIVpUWKEa1Ko8/WO8Y71SQh1UtHdJuLRQkzv1V4gIgbM2N/U+YMHacu4je42dAGdcrm/5GdpT48+Zq23j2UBI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67417},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"}},"gitHead":"24653063b1cf574fffa33023caba912b79fb4ca5","scripts":{"dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","prepare":"husky","prepublishOnly":"npm run build"},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"repository":{"url":"git+https://github.com/CometaLabs/better-auth-passwordless.git","type":"git"},"_npmVersion":"10.8.2","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","directories":{},"_nodeVersion":"20.20.2","allowScripts":{"esbuild@0.27.7":true},"dependencies":{"zod":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","husky":"^9.1.7","typescript":"^5.0.0","@types/node":"^20.0.0","better-auth":"^1"},"peerDependencies":{"better-auth":"^1"},"_npmOperationalInternal":{"tmp":"tmp/better-auth-passwordless_0.1.7_1782074842995_0.04350696410641186","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@cometalabs/better-auth-passwordless","version":"0.1.8","description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.mjs","require":"./dist/server.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs","require":"./dist/client.js"}},"scripts":{"build":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts","dev":"tsup src/index.ts src/server.ts src/client.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","prepublishOnly":"npm run build","prepare":"husky"},"keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","homepage":"https://cometalabs.io","repository":{"type":"git","url":"git+https://github.com/CometaLabs/better-auth-passwordless.git"},"bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"publishConfig":{"access":"public"},"peerDependencies":{"better-auth":"^1"},"dependencies":{"zod":"^4.0.0"},"devDependencies":{"@types/node":"^20.0.0","better-auth":"^1","husky":"^9.1.7","tsup":"^8.0.0","typescript":"^5.0.0"},"allowScripts":{"esbuild@0.27.7":true},"_id":"@cometalabs/better-auth-passwordless@0.1.8","gitHead":"cbd431f8b50aa96926044e0bde5e14d2a77b35a0","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-5rYkSu60PpBwsgyp4Zg3nNa3Uc+Vs/MMs9uah9MpHM0hArIzi5xbQfKXPi2GkBJ+2Wcux/O4OIrIm2Xd8GgcOw==","shasum":"65325c01182ce70cbb2fe34068aea64c3385162a","tarball":"https://registry.npmjs.org/@cometalabs/better-auth-passwordless/-/better-auth-passwordless-0.1.8.tgz","fileCount":16,"unpackedSize":67395,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCC5D+Z68BQUbvrkDPqmFA+9qB9aXco22sTMTV17qr4WAIhAJenBlqxIeawU0KvLBt7VKoGFPdIcxtwo9EcRuWsADUR"}]},"_npmUser":{"name":"emprecario","email":"alex@cometalabs.io"},"directories":{},"maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/better-auth-passwordless_0.1.8_1782150082531_0.973479861857139"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-21T15:47:50.920Z","modified":"2026-06-22T17:41:22.866Z","0.1.0":"2026-06-21T15:47:51.204Z","0.1.1":"2026-06-21T16:00:58.019Z","0.1.4":"2026-06-21T20:07:02.568Z","0.1.5":"2026-06-21T20:21:10.234Z","0.1.6":"2026-06-21T20:32:28.306Z","0.1.7":"2026-06-21T20:47:23.117Z","0.1.8":"2026-06-22T17:41:22.739Z"},"bugs":{"url":"https://github.com/CometaLabs/better-auth-passwordless/issues"},"author":{"name":"Cometalabs","email":"alex@cometalabs.io"},"license":"MIT","homepage":"https://cometalabs.io","keywords":["better-auth","passwordless","otp","magic-link","authentication","plugin"],"repository":{"type":"git","url":"git+https://github.com/CometaLabs/better-auth-passwordless.git"},"description":"Passwordless authentication plugin for Better Auth — OTP codes and magic links via email","maintainers":[{"name":"emprecario","email":"alex@cometalabs.io"}],"readme":"<a href=\"https://cometalabs.io\">\n  <picture>\n    <source srcset=\"https://cometalabs-assets.s3.us-east-1.amazonaws.com/better-auth-passwordless/assets/cometa-banner.png\" />\n    <img alt=\"Cometa\" src=\"https://cometalabs-assets.s3.us-east-1.amazonaws.com/better-auth-passwordless/assets/cometa-banner.png\" />\n  </picture>\n</a>\n\n<br />\n\n# 🔐 better-auth-passwordless\n\n**better-auth-passwordless** is a passwordless authentication plugin for [Better Auth](https://better-auth.com). It enables login without passwords by sending users a **one-time code (OTP)** and/or a **magic link** via email — just like Slack or Linear do it.\n\n## Features\n\n- 🔑 Passwordless login via OTP code or magic link\n- 📧 Single email with both an OTP and a clickable deep link\n- 🔒 Atomic OTP verification to prevent concurrent reuse\n- 🚦 Built-in rate limiting per endpoint\n- 🛡️ Configurable max attempts for both OTP and magic link\n- 🚫 Optional sign-up disable (existing users only)\n- 📦 Full TypeScript support with exported types\n- ⚡️ Works seamlessly as a Better Auth plugin\n\n## Installation\n\n### npm\n```bash\nnpm install @cometalabs/better-auth-passwordless\n```\n\n### pnpm\n```bash\npnpm add @cometalabs/better-auth-passwordless\n```\n\n### bun\n```bash\nbun add @cometalabs/better-auth-passwordless\n```\n\n> Requires `better-auth >= 1.0.0` and `zod >= 4.0.0`\n\n## How it works\n\n1. User enters their email address\n2. Plugin creates a signed token and an OTP, stores them in the verification table\n3. Your `sendEmail` function is called with both the OTP and a magic link URL\n4. User either:\n   - **Clicks the magic link** → instantly authenticated via `GET /passwordless-bundle/verify`\n   - **Enters the OTP code** → authenticated via `POST /passwordless-bundle/verify-otp`\n5. On success, a session is created and the user is redirected or receives a session token\n\n## Usage\n\n### Server setup\n\n```ts\nimport { betterAuth } from \"better-auth\";\nimport { passwordlessBundle } from \"@cometalabs/better-auth-passwordless\";\n// or from the server subpath:\n// import { passwordlessBundle } from \"@cometalabs/better-auth-passwordless/server\";\n\nexport const auth = betterAuth({\n  plugins: [\n    passwordlessBundle({\n      sendEmail: async ({ to, otp, magicLinkUrl, expiresInSeconds, appName }) => {\n        // Send your email here using Resend, Nodemailer, etc.\n        await resend.emails.send({\n          from: \"noreply@yourapp.com\",\n          to,\n          subject: `Your ${appName} login code`,\n          html: `\n            <p>Your login code is: <strong>${otp}</strong></p>\n            <p>Or <a href=\"${magicLinkUrl}\">click here</a> to log in directly.</p>\n            <p>Expires in ${expiresInSeconds / 60} minutes.</p>\n          `,\n        });\n      },\n    }),\n  ],\n});\n```\n\n### Client setup\n\n```ts\nimport { createAuthClient } from \"better-auth/client\";\nimport { passwordlessBundleClient } from \"@cometalabs/better-auth-passwordless\";\n// or from the client subpath:\n// import { passwordlessBundleClient } from \"@cometalabs/better-auth-passwordless/client\";\n\nexport const authClient = createAuthClient({\n  plugins: [passwordlessBundleClient()],\n});\n```\n\n### Requesting a login email\n\n```ts\nawait authClient.passwordlessBundle.request({\n  email: \"user@example.com\",\n  callbackURL: \"/dashboard\",         // redirect after magic link login\n  newUserCallbackURL: \"/onboarding\", // redirect for first-time users (optional)\n  errorCallbackURL: \"/login?error\",  // redirect on error (optional)\n});\n```\n\n### Verifying with OTP\n\n```ts\nawait authClient.passwordlessBundle.verifyOtp({\n  email: \"user@example.com\",\n  otp: \"123456\",\n});\n```\n\n## Configuration options\n\n```ts\npasswordlessBundle({\n  sendEmail: async (payload, ctx) => { /* required */ },\n\n  expiresInSeconds: 300,       // Token/OTP expiry in seconds (default: 300 = 5 min)\n  otpLength: 6,                // Length of the OTP code (default: 6)\n  allowedAttemptsOtp: 3,       // Max OTP verification attempts (default: 3)\n  allowedAttemptsMagicLink: 1, // Max magic link uses (default: 1)\n  disableSignUp: false,        // Block new user creation (default: false)\n\n  rateLimit: {\n    windowSeconds: 60,         // Rate limit window (default: 60s)\n    max: 5,                    // Max requests per window (default: 5)\n  },\n})\n```\n\n### `sendEmail` payload\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `to` | `string` | Recipient email address |\n| `otp` | `string` | The one-time code to display |\n| `magicLinkUrl` | `string` | The full URL for the magic link |\n| `expiresInSeconds` | `number` | Seconds until both expire |\n| `appName` | `string` | Value from `betterAuth({ appName })` |\n| `requestMetadata` | `Record<string, unknown> \\| undefined` | Extra data passed in the request body |\n\n## Endpoints\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/passwordless-bundle/request` | Send OTP + magic link email |\n| `GET` | `/passwordless-bundle/verify` | Verify magic link token (redirects) |\n| `POST` | `/passwordless-bundle/verify-otp` | Verify OTP code |\n\n## Cometa Labs\n\nbetter-auth-passwordless is built with ☄️ by [Cometa Labs](https://cometalabs.io).\n\nSource code: [github.com/CometaLabs/better-auth-passwordless](https://github.com/CometaLabs/better-auth-passwordless)\n\n## Authors\n\n- [Alexei Soliz](https://github.com/emprecario)\n\n## License\n\nMIT - © 2025 Cometa Labs\n\n","readmeFilename":"README.md"}