Documentation
Add sign-up, sign-in, social login and user management to any app. Pick your platform below, or read this page first for how the pieces fit.
How it works
Every app you build is a project in Tausi. A project has its own users (the same email in two projects is two separate accounts), its own settings, and two kinds of key:
| Key | Where it goes | What it can do |
|---|---|---|
pk_… | Your frontend, mobile app or server-rendered pages. It's public. | Sign users up and in, and let them manage their own profile and sessions. |
sk_… | Your backend only, in an environment variable. Never in a browser or app. | Check session tokens and manage every user in the project. |
The flow is always the same:
- Your app signs the user in with the publishable key and gets a session token.
- It sends that token to your API as
Authorization: Bearer <token>. - Your API checks it with the secret key. Tausi answers with the user, or "not valid" if the token is expired, revoked, or the user is banned or suspended.
Set up a project
- Create a project from Projects. Give it your app's name and its URL.
- Allowed origins (project Settings): every web origin your app runs on, such as
https://app.example.comandhttp://localhost:3000. Browser requests and social sign-in redirects are only accepted from these. - App URL: where your app lives. By default, verification and password-reset emails link to
<App URL>/verify-email?token=…and<App URL>/reset-password?token=…. Your app can choose another page per request withredirectTo; see Email links. - Copy the keys from API keys. The secret key is shown once; you can create more and revoke old ones.
- Optional: turn on Google, GitHub, Apple and others under Social sign-in, and set password rules and abuse limits under Security.
Store the keys as environment variables. Every guide uses these names:
TAUSI_URL=https://tausi-auth.onrender.com
TAUSI_PUBLISHABLE_KEY=pk_…
TAUSI_SECRET_KEY=sk_… # server onlyEach project's Quickstart tab has ready-to-paste snippets with that project's real publishable key.
Email links and redirect URLs
Like Supabase's emailRedirectTo, your app can say where each email should send the user. Pass redirectTo when signing up, resending a verification email or asking for a password reset:
await tausi.signUp({ name, email, password, redirectTo: "https://app.example.com/welcome" });
await tausi.sendVerificationEmail(email, { redirectTo: "https://app.example.com/welcome" });
await tausi.forgotPassword(email, { redirectTo: "myapp://auth/reset" }); // a mobile deep linkThe link in the email is your URL plus the token, keeping your own query string:
https://app.example.com/welcome?token=…&type=email_verification
myapp://auth/reset?token=…&type=password_resetThat page reads token (and type, if one page handles both) and calls verifyEmail(token) or resetPassword(token, newPassword). Redeem the token on a click rather than on page load, so email link scanners can't use it up.
Which URLs are accepted
| redirectTo | Accepted when |
|---|---|
| https://… or http://… | its origin is in Allowed origins, or it matches a Redirect URLs entry |
| Deep links (myapp://…) | it matches a Redirect URLs entry |
| Anything else | refused with REDIRECT_NOT_ALLOWED (400), and nothing is sent or created |
Add entries under project Settings → Redirect URLs, one per line. * matches one host label or path segment and ** matches anything, e.g. https://*.preview.example.com/auth/** for preview deployments. javascript:, data: and a bare * host are never allowed.
myapp://. For mobile apps, prefer an https App Link / Universal Link on an allowed origin, which opens the app when it's installed and your website otherwise.Protecting accounts
Each project's Settings and Security tabs control how hard it is to abuse your sign-up and sign-in:
| Protection | What it does | Default |
|---|---|---|
| Breached passwords | Refuses passwords from known data breaches (Have I Been Pwned, k-anonymity: the password never leaves Tausi). PASSWORD_BREACHED. | On |
| New-device emails | Emails the user when their account signs in from a browser or app it hasn't used in 180 days. | On |
| Bot protection | Cloudflare Turnstile or hCaptcha on sign-up, forgot-password and optionally sign-in, verified by Tausi. | Off |
| Reveal taken emails | Sign-up says EMAIL_ALREADY_REGISTERED. Off: it answers as for a new account, so nobody can probe which emails have accounts. | Off for new projects |
| Rate limits | Per IP and per email on sign-in, sign-up, resets and verification emails. | Always |
| Bans and suspensions | Blocks every way of signing in; see Managing users. | — |
Adding the bot check
const captcha = await tausi.getCaptchaConfig(); // { provider: "turnstile", siteKey, actions } or null
// Render the provider's widget with captcha.siteKey (e.g. <div class="cf-turnstile" data-sitekey="…">),
// then pass the token it produces:
await tausi.signUp({ name, email, password, captchaToken: turnstileToken });
await tausi.signIn({ email, password, captchaToken }); // only if "sign_in" is in captcha.actions
await tausi.forgotPassword(email, { captchaToken });Python: captcha_token=; PHP: the last argument $captchaToken; Flutter: captchaToken:. Over plain HTTP, send it as the X-Tausi-Captcha header.
Secret keys
Create one key per service under API keys. A key can be read-only (verify sessions and read users) and can be limited to your servers' IP addresses. Each key is rate-limited, and the first use from a new IP is logged as security.secret_key_new_ip.
Platforms
Install
| Platform | Package | Install |
|---|---|---|
| Next.js, React, Vue, Svelte, any browser app | @tausi-auth/js (npm) | npm install @tausi-auth/js |
| Node.js backends, Electron, React Native | @tausi-auth/node (npm) | npm install @tausi-auth/node |
| Python, Django, Flask, FastAPI | tausi (PyPI) | pip install "tausi[django]" |
| PHP, Laravel | tausi/tausi-php (Packagist) | composer require tausi/tausi-php |
| Flutter | tausi_flutter (pub.dev) | Not published yet |
| AI coding tools (MCP) | @tausi-auth/mcp (npm) | npx -y @tausi-auth/mcp --help |
Each platform page shows the command for every package manager (npm, pnpm, yarn, bun; pip, uv, poetry). You can mix SDKs: a Flutter app and a Next.js site can share one project, with a Python or PHP API checking the same tokens.
The user object
Every SDK returns the same user. Optional attributes can be set at sign-up or edited by the user; metadata is written by your backend.
{
"id": "3021ZWj6Mx4xIfoxX9JHkC4Ph1M4ZNLQ",
"email": "asha@example.com", "emailVerified": true,
"name": "Asha Mwangi", "firstName": "Asha", "lastName": "Mwangi",
"username": "asha", "image": null,
"phoneNumber": "+255712345678", "phoneNumberVerified": false,
"locale": "sw-TZ", "timezone": "Africa/Dar_es_Salaam",
"role": "user", "publicMetadata": { "plan": "pro" },
"lastSignInAt": "2026-11-03T09:12:00.000Z",
"createdAt": "…", "updatedAt": "…"
}With the secret key you also get privateMetadata, status (signed_in / signed_out), activeSessions, lastActiveAt, lastSignOutAt, signInCount and access (active, suspended or banned). See Managing users.
Next steps
- Errors have a stable
codein every SDK. Branch on it, not on the message: error codes. - Everything the SDKs do is plain HTTP, so any language works: HTTP API.
- Each SDK's README in the repository (
sdks/) lists every method.