ZeepNotti Docs
First Steps & SettingsZeepNotti dashboard

Emails & Account Recovery

Which emails ZeepNotti sends and when, password reset and email verification, auth rate limits, and the environment variables that control email and client IP resolution on self-hosted installs.

ZeepNotti sends HTML emails (with a plain-text alternative) for account events, security events and operational problems with your Apps. On SaaS they are delivered by Zeep; on a self-hosted install they go through the Company's SendGrid key (Company Settings). If a self-hosted Company has no SendGrid key, emails are skipped and logged - nothing else breaks.

Every email except invites is sent in the background by the worker, with retries. A failed email never fails the action that triggered it.

Emails sent

Alerts go to every Owner of the Company. Alerts with a dedup window are sent at most once per window - a burst of identical failures produces one email, not one per delivery.

EmailSent whenRecipientDedup
invite-new-userSomeone without an account is invitedInvitee-
company-addedAn existing account is added to a CompanyInvitee-
welcomeOnboarding creates a CompanyNew Owner-
verify-emailOnboarding, or Resend email from the dashboard bannerThe user60s throttle
password-resetForgot password? is submitted for an existing accountThe user60s throttle
member-removedAn Owner removes a memberRemoved member-
access-changedAn Owner changes a member's role or App accessThat memberOnly when something actually changed
key-rotatedA REST or Client key is rotatedOwnersNone - every rotation
provider-not-configuredA delivery fails because FCM/APNs is not configuredOwnersOnce per App + platform per 24h
app-disabled-pendingPending deliveries are failed because the App was disabledOwnersOnce per disable event
mau-exceededA notification is rejected by the MAU limit (SaaS)OwnersOnce per App per 30 days
limit-reachedAn invite or App creation is rejected by the plan's user/App limit (SaaS)OwnersOnce per Company + resource per 24h
delivery-digestDaily: an App had ≥100 deliveries and ≥10% failed the previous UTC dayOwnersOnce per App per day
invalid-tokensDaily: provider-invalidated devices for an App/platform were ≥500, or ≥5% of its subscribed base, the previous UTC dayOwnersOnce per App + platform per day
mau-warningDaily: a SaaS App's MAU crossed 80% or 90% of its plan limitOwnersOnce per threshold per App per 30 days

The daily checks run hourly on every worker and always look at the previous UTC day; the dedup record makes sure each email is sent exactly once even with several worker replicas.

Key-rotation emails include only the key prefix (rk_/ck_ plus the first 4 characters), never the key itself. There are no per-user alert preferences yet - every Owner receives every alert.

Password reset

  1. On the login screen, click Forgot password? and enter your email. ZeepNotti always answers the same way, whether or not the account exists, so the form can't be used to discover who has an account.
  2. If the account exists, a password-reset email arrives with a link to /reset-password. The link is single-use and expires after 1 hour. Requesting again within 60 seconds does not send another email.
  3. Choose a new password. Once it's saved:
    • every other outstanding reset link for that account stops working;
    • every session and refresh token issued before the reset is rejected, so other signed-in browsers are signed out on their next request;
    • the email address is marked as verified.

An invalid, expired or already-used link shows an error with a Request a new link action.

Rate limits

The public account endpoints are rate limited per client IP, in fixed 1-minute windows shared by every server replica (counters live in Redis). Going over the budget answers 429 rate_limited with a Retry-After header in seconds.

EndpointRequests per minute
POST /v1/auth/login10
POST /v1/auth/forgot-password5
POST /v1/auth/reset-password10
POST /v1/auth/verify-email10
POST /v1/auth/accept-invite10
POST /v1/auth/refresh30
POST /v1/companies (onboarding)5

If Redis is unreachable the limits are skipped (requests go through) and the error is logged, so an outage never locks admins out.

Email verification

New Owners get a verify-email message during onboarding. The link opens /verify-email, is single-use and expires after 24 hours. Until the address is verified, the dashboard shows a dismissible banner with a Resend email action.

Accepting an invite or resetting a password also marks the address as verified, since both prove you can read that mailbox. Verification is informational today: an unverified account can still sign in and use the dashboard.

Self-hosted configuration

VariableRequiredDescription
NOTTI_DASHBOARD_BASE_URLYes, for emailPublic dashboard origin (e.g. https://notti.example.com). Every link in an email - invite, password reset, verification, alerts - is built from it.
NOTTI_INVITE_TOKEN_SECRETYes, to invite membersSigns member invite links.
NOTTI_EMAIL_FROM_ADDRESSYes, for SendGridSender address for emails sent through the Company's SendGrid key.
NOTTI_EMAIL_LOGO_URLNoAbsolute https URL of the logo shown in emails. Defaults to {NOTTI_DASHBOARD_BASE_URL}/email/notti-logo-white.png, served by ZeepNotti itself. Set it when the dashboard isn't reachable from your recipients' mail clients (e.g. a private network), otherwise the logo shows as alt text.
NOTTI_DOCS_URLNoDocs link in the welcome email. Defaults to https://docs.zeepnotti.app.
NOTTI_TRUSTED_PROXIESBehind a proxyComma-separated CIDRs (e.g. 10.0.0.0/8,fd00::/8) of the reverse proxies or load balancers in front of ZeepNotti. When a request comes from one of them, the client IP is the right-most X-Forwarded-For entry that isn't itself a trusted proxy. Unset, the TCP peer address is used and X-Forwarded-For is ignored - behind a proxy that means every client shares the proxy's rate-limit budget. An invalid CIDR fails startup.

ZEEP_NOTIFICATIONS_BASE_URL and ZEEP_NOTIFICATIONS_API_KEY configure email delivery for the SaaS deployment only; self-hosted installs don't need them.

On this page