TausiDocs

Managing users

Everything you can do to a project's users, from the dashboard (Project → Users) or from your backend with the secret key. Changes are recorded in the project's audit log.

Profile attributes

AttributeRulesWho sets it
name1–100 characters. Required at sign-up.User, backend
firstName1–100 characters.User, backend
lastName1–100 characters.User, backend
username3–32 of a–z 0–9 . _ -, starting and ending with a letter or digit. Stored lower-case, unique per project (USERNAME_TAKEN).User, backend
phoneNumberInternational format; spaces, dashes and brackets are removed (+255712345678).User, backend
phoneNumberVerifiedTausi doesn't send SMS: your backend marks it after its own check. Changing the number resets it.Backend
localeLanguage tag such as en, sw or sw-TZ.User, backend
timezoneIANA zone such as Africa/Dar_es_Salaam.User, backend
emailVerifiedSet by the verification link, or by you.Backend, dashboard
roleuser or admin.Dashboard only

Users can set the attributes at sign-up and edit them later (send null to clear one). Email changes aren't supported yet.

Metadata

Two JSON objects per user, each up to 8 KB, written only by your backend. Each write replaces the whole object.

FieldReadable byUse it for
publicMetadataThe user (returned on sign-in, /users/me and session checks) and your backendPlan, feature flags, onboarding step
privateMetadataYour backend and the dashboard onlyBilling IDs, internal notes, risk scores
Node exampleTypeScript
await tausi.users.update(userId, {
  publicMetadata: { plan: "pro", seats: 5 },
  privateMetadata: { stripeCustomerId: "cus_123" },
});

Sign-in state and activity

FieldMeaning
statussigned_in while the user has at least one unexpired session, otherwise signed_out.
activeSessionsNumber of unexpired sessions (devices).
lastSignInAtLatest successful sign-in: password, two-factor or social.
lastActiveAtLatest activity over all sessions (updated at most every few minutes).
lastSignOutAtLatest explicit sign-out.
signInCountSuccessful sign-ins so far.

Ban and suspend

BanSuspend
LastsUntil you unban1 minute to 1 year, then lifts by itself
On applyEvery session is revoked at onceEvery session is revoked at once
Sign-inRefused with ACCOUNT_BANNEDRefused with ACCOUNT_SUSPENDED (details.suspendedUntil)
CoversPassword, two-factor and social sign-inPassword, two-factor and social sign-in
DataKeptKept
  • The refusal only comes after a correct password. A wrong password still gets INVALID_CREDENTIALS, so a ban can't be discovered by guessing.
  • Social sign-in returns to your app with ?tausi_error=account_banned or account_suspended.
  • The optional reason (up to 500 characters) is an internal note. Users are never shown it.
  • Session checks from your backend (verifySession, authenticateRequest) return null for blocked users.
  • Filter lists with access=active, suspended or banned.
HTTPHTTP
POST   /api/v1/backend/users/:id/ban        { "reason": "Spam" }
DELETE /api/v1/backend/users/:id/ban
POST   /api/v1/backend/users/:id/suspend    { "durationHours": 24, "reason": "Chargeback" }   # or { "until": "2026-12-01T00:00:00Z" }
DELETE /api/v1/backend/users/:id/suspend

Bulk actions

In the dashboard, tick users (or the header box for the whole page) and pick an action. From your backend, send up to 100 IDs. Each user succeeds or fails on its own, and the response says which.

POST /api/v1/backend/users/bulkJSON
{ "action": "suspend", "ids": ["u1", "u2", "u3"], "durationHours": 72, "reason": "Fraud review" }

→ { "results": [{ "id": "u1", "ok": true }, { "id": "u3", "ok": false, "error": { "code": "NOT_FOUND", "message": "User not found." } }],
    "succeeded": 2, "failed": 1 }

Actions: delete, ban, unban, suspend, unsuspend, revoke_sessions, verify_email.

Sessions and devices

Open a user in the dashboard to see every active session with its device (browser and version, operating system, desktop / mobile / tablet, or a server-side SDK), IP address, sign-in time, last activity and expiry, and to revoke any of them. Below it, the sign-in history lists the last 50 sign-ins and sign-outs, including failed attempts and why they failed.

From your backend: GET /backend/users/:id returns sessions and signInHistory; POST /backend/users/:id/revoke-sessions signs the user out everywhere. Users can manage their own devices with listSessions, revokeSession and revokeOtherSessions in every client SDK.

Deleting users

Deleting removes the account, its credentials and every session permanently. The audit log keeps only the opaque user ID. In the dashboard you confirm by typing the user's email (or delete N for several) and entering your password.

Consider a ban first
A ban is reversible and keeps the user's data, which you may need for disputes or legal holds.

In each SDK

ActionNodePythonPHP
Listusers.list({ access })users.list(access=)listUsers([...])
Detailsusers.get(id)users.get(id)getUser($id)
Updateusers.update(id, patch)users.update(id, ...)updateUser($id, [...])
Banusers.ban(id, { reason })users.ban(id, reason=)banUser($id, $reason)
Unbanusers.unban(id)users.unban(id)unbanUser($id)
Suspendusers.suspend(id, { durationHours })users.suspend(id, hours=)suspendUser($id, $until)
Lift suspensionusers.unsuspend(id)users.unsuspend(id)unsuspendUser($id)
Bulkusers.bulk(action, ids)users.bulk(action, ids)bulkUsers($action, $ids)
Sign out everywhereusers.revokeSessions(id)users.revoke_sessions(id)revokeUserSessions($id)
Deleteusers.delete(id)users.delete(id)deleteUser($id)

A secret key can't change roles; that's only possible in the dashboard.