AdministrationYour account

Account settings

Everything on this page is personal to you — it changes how Neens looks, speaks, and emails you, never what you or anyone else is allowed to do. Most of it lives under Settings → Account; your view and language are also switchable from the topbar.

At a glance

WhereSettings → Account; topbar switchers for language and view
Key API routesPOST /auth/change-password, POST /auth/forgot-password, GET /auth/mfa, POST /auth/mfa/enroll, POST /auth/mfa/verify, POST /auth/mfa/challenge, POST /auth/mfa/recovery-codes, POST /auth/mfa/disable, GET /auth/sessions, DELETE /auth/sessions/{id}, POST /auth/sessions/revoke-all, PUT /auth/locale, PUT /auth/digest, POST /auth/digest/test, PUT /auth/persona, PUT /scores/prefs
ScopePer user (score favorites are per user and per agent)
Permission impactNone — these are presentation, security and notification settings for your own account

Change your password

Under Settings → Account, the Password card asks for your current password even though you’re already signed in — a hijacked-but-idle session can’t silently rotate your credential. The new password has to be different from the current one and has to clear the password rules below (POST /auth/change-password).

On success, every other session is signed out (other devices, and anyone who shouldn’t have been there) and your current device gets a fresh session, so you stay signed in. Neens also emails you that your password changed — see Security emails.

Password rules

Every password field shows the live rules underneath it, read from the server, so you never have to guess. The defaults:

  • At least 12 characters. Length is the rule that matters. There is deliberately no “one uppercase, one number, one symbol” requirement — those push everyone toward Password1!, which is one of the most-guessed passwords in existence, while rejecting a genuinely strong passphrase for having no digit. A memorable phrase of several words is both stronger and easier to type.
  • Not a known-breached password. Your candidate is checked against a list of passwords that appear in public breach dumps and cracking lists. This is a local check — your password is never sent anywhere to be checked.
  • Not your own details. It can’t contain your name, email address, or company name.
  • Not a predictable shape. Keyboard walks (qwertyuiop), long repeated or sequential runs, and a single word with a year on the end (Sunflower2026) are refused — cracking tools generate those exhaustively.

If a password is refused, the message says which rule it hit and what to do instead.

These rules apply when you set a password — activating an invite, changing it, or completing a reset. They are never applied when you sign in, so an older password that no longer meets the minimum keeps working until you next change it. Your operator can raise the minimum; it can’t be lowered below 8.

Two-factor authentication

A second factor is what makes a stolen password insufficient on its own. Neens supports TOTP — the 6-digit code that rolls over every 30 seconds in an authenticator app — plus a set of one-time recovery codes for the day your phone isn’t with you. It lives under Settings → Account → Two-factor authentication.

Any RFC 6238 authenticator works. Neens hands your app a standard otpauth://totp/… secret and never contacts the app’s vendor; codes are computed on your device and verified on the server. There is no SMS anywhere in this flow, and nothing to install on your phone that Neens has to approve.

Turn it on

Open Settings → Account → Two-factor authentication

Set up two-factor authentication issues you a secret (POST /auth/mfa/enroll). Issuing it changes nothing yet: your account keeps signing in exactly as it does today until you finish the last step below. An enrollment you abandon halfway — a dead phone battery, a closed tab — leaves you fully able to get in, and starting again simply replaces the half-set-up secret.

Add the secret to your authenticator

Scan the QR code with your authenticator app. If the thing you’re enrolling can’t scan — a desktop authenticator, a password manager, a hardware token app — use the base32 setup key shown beside the QR (it looks like JBSWY3DPEHPK3PXP) and type it in. Both encode the same thing: a 6-digit code on a 30-second period.

Enter your password and the current 6-digit code

Type your current sign-in password and the code your app is showing, then confirm (POST /auth/mfa/verify). This is the step that enables MFA — Neens will never switch it on for a secret it has not yet seen a working code from, because “enabled on issue” is the classic way a mistyped setup locks somebody out of their own account.

curl -X POST https://your-neens-host/auth/mfa/verify \
  -H "Authorization: Bearer $NEENS_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"password": "your-current-password", "code": "123456"}'
{
  "enabled": true,
  "enrolledAt": "2026-07-31T14:02:11.417329+00:00",
  "recoveryCodes": ["k7m2q-9xf4t", "b3n8p-2wd6r", "…"]
}

Why it asks for your password again, when you just signed in with it. Turning a second factor on decides who owns the account from that moment. Without this step, anybody who had your password could enroll their authenticator on your account — and you would then be the one locked out, with no way to remove a factor you never set up. It is the same password prompt that turning the feature off and regenerating your recovery codes have always asked for; it was missing from the one step that establishes the factor rather than removing it.

It is asked here and not when you press Set up two-factor authentication, so an abandoned setup still costs nothing.

A wrong password — or a request that omits the field — returns 401 {"detail": "Current password is incorrect."}. The two answers are deliberately identical, so the response never reveals which of the two you got wrong. Nothing is enabled and no recovery codes are issued. Too many wrong passwords in a row pause the account the same way too many wrong codes do (see “Too many attempts” below).

Save your 10 recovery codes

You are then shown 10 recovery codes, each of the form k7m2q-9xf4t. They are displayed exactly once, on that screen — Neens stores only hashes of them, the same way it stores your password, so nobody (including your operator) can show them to you a second time. Each code works once. Copy them somewhere you can reach without your phone: a password manager on another device, or printed and kept where you keep your passport.

⚠️

Leaving that screen without saving the codes is the one irreversible mistake in this flow. If you did, you’re not locked out — sign in with your authenticator and use Regenerate recovery codes below, which issues a fresh ten and invalidates the ones you lost.

Signing in once it’s on

Enter your email and password as usual

Neens answers with a challenge rather than a session — nothing is signed in yet (POST /auth/login returns a short-lived challenge instead of a session token). The page asks for your code.

Enter the 6-digit code from your authenticator

Confirm (POST /auth/mfa/challenge). On success your session is issued and you land where you were heading.

Or use a recovery code instead

Use a recovery code on the same screen takes one of your ten. Paste it with or without the hyphen — k7m2q-9xf4t and k7m2q9xf4t are both accepted. The code is spent the moment it works, and the response tells you how many you have left. At two or three remaining, regenerate.

The code screen lasts 5 minutes and allows a few tries. A mistyped code just tells you it was wrong — type the next one. But that screen expires after 5 minutes and gives up after a handful of wrong codes. When it does, you go back to the email-and-password screen and sign in again for a fresh one; nothing is wrong with your account. The message is the same either way, so don’t read anything into which of the two you hit.

“Too many attempts” on the code screen. After a few wrong codes in a row the code screen pauses before it will take another, and the wait grows if you keep going — the page shows a countdown and re-enables itself. Signing in again does not clear it: the pause follows your account, not the code screen, which is the whole point of it. Three things end it, in the order worth trying:

  1. Wait it out. The countdown is short at first (a couple of seconds) and never longer than a few minutes.
  2. Enter a correct code. One code that actually works clears the pause immediately. If you have run out of patience with the authenticator, Use a recovery code counts too.
  3. Try from another network. After enough wrong codes from one place, that place is blocked for a while rather than your account — so your phone’s mobile data, or home instead of the office, usually just works.

If none of those apply, your authenticator has probably drifted or been lost — see If you lose your authenticator. An operator can reset the second factor for you, which clears the pause with it.

Rules that catch people out

RuleWhat it means for you
A password reset does not bypass MFA.Completing Forgot password changes your password and then still asks for your code before it signs you in. Mailbox access alone is not a way past the second factor.
A code is valid exactly once.Re-submitting the same 6 digits fails even while your app is still showing them — for example after a flaky network retry. Wait for the next code.
The accepted window is ±30 seconds, and no wider.Neens accepts the current code and one step either side. If your codes are always rejected, your phone’s clock has drifted: turn on automatic/network time and try again.
API keys carry no second factor.A nk_live_… or nk_admin_… key is used by machines, so it can’t be challenged. Minting one with operator scope therefore asks for a current code (or a session that entered one in the last 15 minutes) — otherwise key issuance would be a quiet way back to exactly the access MFA is protecting. See API keys.

Regenerate your recovery codes

Regenerate recovery codes asks for your password and a current code, then issues a fresh set of ten (POST /auth/mfa/recovery-codes). It replaces all outstanding codes — used and unused — so any old printout stops working immediately. Like enrollment, the new codes are shown once.

Turn it off

Turn off two-factor authentication asks for your password and a current code (POST /auth/mfa/disable); a recovery code is accepted in place of the code. Both are required on purpose — an attacker sitting in a session you left open should not be able to strip the control that would have stopped them.

⚠️

Operator accounts can’t turn it off. On a deployment where MFA is required for the platform operator, that request is refused (mfa_required_for_operator). Turning it off is also not the tool for “I got a new phone” on any account: sign in with a recovery code, regenerate your codes, and enroll the new device.

Emails Neens sends when your second factor changes

Three things can change your second factor, and Neens emails you about each one — exactly one message per event, to your account address. They are the only signal that reaches you outside the account, which matters precisely when the account is the thing that has been taken.

You’ll getWhen it firesWhat’s in itWhat to do if you weren’t expecting it
”Two-factor authentication was turned on”Someone completed POST /auth/mfa/verify on your accountThe time, and the IP address it was set up from when one is knownSomebody knows your password and has enrolled their own authenticator. Change your password immediately, then ask an administrator to reset two-factor authentication for you — you cannot remove a factor you did not enroll
”Two-factor authentication was turned off”Someone completed POST /auth/mfa/disableThe time, the IP address when known, and a reminder that your password is now the only thing protecting the accountChange your password immediately and turn two-factor authentication back on
”Two-factor authentication was reset”An operator ran the reset from Settings → MembersThe time and who did it — the acting operator’s address. You are signed out everywhereYou are now password-only and somebody else arranged that. Change your password immediately and contact your administrator

Every one of these:

  • Never contains a secret. No setup key, no recovery code, no session or challenge token. The link in them points at the token-free Forgot password page, so an attacker reading your mailbox gains nothing from the message itself.
  • Names an IP address only when one is known and is genuinely an address — a missing or unparseable value is left out rather than printed as “unknown”. Depending on how your deployment is fronted, that address may be one the caller supplied, so treat it as a lead, not as proof. The reset notice carries no address at all: the person who acted was an operator, not you, so it names them instead.
  • Is sent in your language, from your account’s locale preference.
  • Is best-effort. A mail outage never blocks the change itself, so “I got no email” is not proof that nothing happened.

If you lose your authenticator

You still haveWhat to do
A recovery codeSign in with it, then Regenerate recovery codes and set up your new device (turn MFA off and on again, or re-enroll from the new phone).
Neither your authenticator nor a recovery codeNothing can be recovered — the codes are hashed and the secret is encrypted — but your operator can reset two-factor authentication on your account, from Settings → Members. Expect them to verify who you are through some channel other than the account itself. The reset signs you out everywhere, then your next sign-in works on your password alone and asks you to enroll again.

If your account is required to have MFA

Most deployments require MFA for the platform operator account, and may require it for company admins. “Required” here does not mean your password stops working. You sign in normally, and then the app takes you straight to the enrollment screen: until you finish it, your session can reach your own account page and nothing else, and any other request answers 403 mfa_enrollment_required. Finishing enrollment lifts that on every device you are signed in on.

Forgot your password?

Use Forgot password on the sign-in page (POST /auth/forgot-password):

Enter your email

The response is identical whether or not the email is registered — Neens deliberately never confirms which addresses exist, so the form can’t be used to enumerate accounts. A reset email is sent only if the address belongs to an active account that already has a password.

The link is single-use and expires after 60 minutes. The reset page checks the token before showing the form, so an expired link tells you immediately.

Set a new password

Completing the reset (POST /auth/reset-password) burns the token, revokes all prior sessions, and signs you in fresh.

If you have two-factor authentication on, the last part changes: your new password is saved, but no session is issued until you answer a code challenge. A reset is a password recovery, not an MFA bypass.

Invited teammates who never set a password use their activation link instead — the reset flow is only for accounts that already have one. If your deployment has no email relay configured, the reset message (including the link) is written to the server logs, so an operator can still hand it to you.

“Too many sign-in attempts”? After several wrong passwords in a row, sign-in pauses for a short, growing wait — the page shows a countdown and re-enables itself. You don’t have to do anything but wait. If you can’t wait, Forgot password still works: password reset is never blocked by this, and completing one clears the pause immediately.

Active sessions

Settings → Account → Active sessions lists every device currently signed in to your account, so you can spot one you don’t recognise and end it. Each entry shows:

DeviceBrowser and platform, read from the session’s user agent — “Chrome · macOS”. Hover for the full string.
IP addressThe address that session connected from, with a badge saying how much that address can be trusted.
Signed in / Last used / ExpiresWhen the session started, when it was last used, and when it runs out.
This deviceA green pill on the session you’re using right now.

The IP badge is the same one used on the sign-in activity trail: Edge header, Proxy hop and Socket peer are addresses your deployment’s own infrastructure observed, while an amber Unverified means the address was supplied by the client and shouldn’t be read as a fact. Sessions created before this feature existed show no address at all rather than a placeholder.

No location lookup is performed. Neens shows the IP address and how trustworthy it is — never a city or country. Turning an address into a place means shipping a geolocation database or calling a third party from your account page, and the answer is wrong often enough (VPNs, mobile carriers, cloud egress) that it would send you chasing a session that was your own all along.

Sign a device out

Revoke one session

Revoke on any row ends that session immediately (DELETE /auth/sessions/{id}). The device is signed out the next time it makes a request. Revoking the row marked This device signs you out and returns you to the sign-in page.

Or sign out everywhere

Sign out other devices ends every session except the one you’re using (POST /auth/sessions/revoke-all), after a confirmation. Your current session is deliberately kept so you don’t lose the tab you’re reacting in.

⚠️

If you think someone else has your password, do both: change your password (which by itself signs out every other session) and check this list afterwards. Signing out other devices alone evicts whoever is there; it does not stop them signing back in with a credential they still know. Then turn on two-factor authentication, which is the only one of these that makes the leaked password insufficient rather than merely stale.

Security emails you may receive

Neens emails you — the account owner — about things only you can judge. You never opt in to these; they are the way a real compromise usually gets noticed.

EmailSent when
Your password was changedSomeone completed a password change from a signed-in session. Includes when, and the IP address it came from when that address is known.
Your password reset is completeA password reset finished against your account, and the reset link that did it is now spent.
Failed sign-in attempts on your accountA run of failed sign-ins hit your account. No one got in — this is a heads-up, not a breach notice.

If any of them was not you, use Forgot password to reset immediately and then review your active sessions.

The security emails never contain a reset link or token — they point you at the reset page, where you request a fresh link. A repeated attack sends one “failed sign-in attempts” email per hour at most, so a sustained attempt can’t be turned into a way of flooding your inbox.

Interface language

Pick your language from the topbar switcher or Settings → Account (PUT /auth/locale). The choice is stored on your profile and applies to the UI, API error messages, and the emails Neens sends you.

Supported languages: English (en), Spanish (es), French (fr), German (de), Italian (it), Portuguese (pt), Arabic (ar), and Japanese (ja). Arabic sets the interface to right-to-left text direction (the layout itself is not mirrored yet). Every one of them is fully translated — the interface never falls back to English behind your back.

Before you sign in there is no switcher: Neens guesses from your browser’s Accept-Language. Your first sign-in back-fills whatever language you were reading onto your profile, and from then on the stored value wins on every device until you change it here.

See Languages for the full picture: asking for a language from an API client with Accept-Language, which surfaces are translated, and the short list of strings that stay in English on purpose.

Digest email

An opt-in summary of your fleet — health tiles plus the insights routed to your view — delivered by email at most once a day.

  • Toggle it on under Settings → Account and pick a cadence: daily or weekly (PUT /auth/digest). It’s off by default.
  • The scheduled job sends daily digests at around 13:00 UTC; weekly digests go out roughly every seven days.
  • Send test digest (POST /auth/digest/test) composes and sends yours right now, without consuming the day’s scheduled send — handy for checking what it will look like.
  • The digest only ever contains data from agents you can see, and opting out remembers your cadence for the next opt-in.

Sending requires the deployment to have an email transport configured; the test button returns an error otherwise. On no-relay installs the scheduled digest is logged server-side instead of silently dropped.

Your view (persona)

Your view decides which nav items are featured, your landing page, and your default time range — never your permissions. Switch it from the topbar View switcher or PUT /auth/persona; an explicit pick is yours and won’t be overridden by an admin default later. The first time you sign in, a one-time picker offers your admin’s recommendation or a role-based suggestion — picking or skipping both dismiss it for good.

See Views (personas) for the built-in views and custom authoring.

Score favorites

On the Scores page you can star score types you watch closely and hide ones that are noise to you (PUT /scores/prefs). Favorites float to the top; hidden metrics collapse out of the way (unhide before re-favoriting). These preferences are yours alone, kept per agent, and don’t enable or disable the underlying judges — though the page offers the related judge controls inline for those with permission.

  • Views (personas) — what each view emphasizes and how defaults are assigned.
  • Members & roles — the permissions your account actually has.
  • API keys — the machine credentials that carry no second factor, and what that means for minting one.
  • Scores — the score catalogue your favorites organize.