MahWins

Privacy Policy

Last updated: September 16, 2026

MahWins ("we", "us") is a Mahjong tracking app for iOS and Android. On the web at mahwins.com you can sign in to the same account to see your groups, log and edit games, and, if you run a league, manage it and buy a league plan. The web uses the same data described here, plus what the Leagues section below adds. This policy explains what information we collect, how we use it, and the choices you have. We keep things simple and collect only what's needed to run the app.

Information We Collect Through the App

Account information

When you create an account with email and password, you give us your email address, a display name, a preset accent color, and optionally a profile photo. Passwords are hashed with bcrypt โ€” no one at MahWins ever sees or can recover your plaintext password.

If you sign in with Apple, we receive an opaque Apple user ID and the email address Apple shares with us (which may be an Apple Private Relay address). We never see your Apple password.

If you sign in with Google, we receive your Google account ID and the email address associated with that account. We never see your Google password. Sign in with Google is available in the iOS and Android apps and on the web dashboard.

Before an email-based account is created we send a one-time verification code to your email address. Codes are hashed, expire in 15 minutes, and are rate-limited.

Game, group, and social data

Every game you log โ€” the winner (or that it was a wall or unfinished game), the winning hand, scoring details (such as self-draw, jokerless, and other point modifiers), the resulting points, your notes, the timestamp, and any photo you attach โ€” is stored on our servers so you can access your history from any device. If you add a guest player who isn't a MahWins user, the name you enter for them is stored with that game. Games you log inside a group are visible to the other members of that group, and any comments members leave on a game are stored and shown to the group. Group data includes the group's name, emoji, color, optional avatar, join code, membership, roles (owner, admin, member), whether score tracking is turned on, and any seasons the group has started. Friends lists, pending friend requests, blocks, and any abuse reports you submit are stored so we can operate those features and review reports.

Photos

Photos you attach to a game or use as an avatar are uploaded to our servers and stored outside of public web access. Only you and the members of the group the game belongs to can view a game photo. We do not use your photos for advertising, training machine-learning models, or any purpose beyond showing them back to you and your group.

Device tokens (push notifications)

If you enable push notifications, your device registers a push token with us so we can notify you about friend requests, group invites, comments on your games, and similar events. Push is delivered through Apple's Push Notification service (APNs) on iOS and through Firebase Cloud Messaging (FCM, a Google service) on Android. The push token is a per-install identifier issued by APNs or FCM โ€” not a Google or Apple account ID. Tokens are removed when you log out, delete your account, or when APNs/FCM tells us they're no longer valid.

Security and operational logs

We keep operational logs in a separate database to run the service safely:

  • API request logs โ€” method, normalized path (e.g. /games/:id, never the actual ID), status code, response time, app version, platform, IP address, and user agent.
  • Error logs โ€” error message and stack trace alongside the same request context, so we can fix bugs.
  • Authentication events โ€” sign-up, sign-in, sign-out, password reset, account deletion, and similar events along with IP, user agent, and platform โ€” used to detect compromised accounts.
  • Email and push delivery records โ€” recipient, template type, delivery status. Push delivery records store only the last 16 characters of the device token, never the full token.
  • Rate-limit hits โ€” when a request is throttled, we record the route and identifier so we can tune limits and detect abuse.

Failed login attempts are tracked briefly to throttle brute-force attempts and are cleared on a successful sign-in. Verification and password-reset codes are hashed before storage, expire after fifteen minutes, and are rate-limited.

App permissions

Both the iOS and Android apps request camera access to scan group-invite QR codes and to take photos when logging a game. To choose an existing photo, the app opens your system photo picker and receives only the image you select โ€” on Android this is the built-in Android Photo Picker, so the app does not request broad access to your photo library. Older Android versions may prompt for storage access when you save a winning-hand photo back to your own gallery. On Android 13 and later, the app asks for notification permission the first time it needs to send a push. We only read from your camera or photos when you tap to take, pick, or save a photo โ€” nothing is accessed in the background.

Information We Don't Collect

MahWins does not use analytics SDKs, crash-reporting SDKs, advertising SDKs, location services, or contact-book access. We do not track you across other apps or websites, sell your data, or use your data to train machine-learning models.

Leagues

A league is a group with a league plan. Its organizers (the group's owner and admins) get a few more tools, and those tools involve some extra data.

Players added by name

An organizer can add players to their league by name, with an email address if they have one, and log games on their behalf. If that is you and you have no MahWins account, we hold the name your organizer entered, that email if they gave one, and the games logged for you, so the league's standings are complete. We do not email that address on our own; if it already belongs to a MahWins account, that account simply gets a normal group invitation. When you sign up with the same email, enter the claim code your organizer gives you, or accept a link request from your organizer, those games move into your own account. An organizer can take a player they added off the roster at any time; the games stay in the league's history. If you want a name removed, ask your organizer or email us.

Public standings pages

An organizer can create a public standings page for their league and share the link. Anyone with the link can open it, with no sign-in, and see the league's players by display name, their wins and points, and each game's result, winning hand and table. Your organizer decides whether that page exists and can turn it off or replace the link at any time. If you would rather not appear on a public page, tell your organizer or email us.

Plans and payments

League plans are bought on mahwins.com and paid through Stripe. Stripe collects your card details on its own pages; they never reach us. We send Stripe the email you enter at checkout, the plan you chose and the league's name, and we keep the purchase record (plan, seats, dates, status) together with Stripe's customer, subscription and receipt identifiers for as long as we need them for accounting and tax purposes. Stripe's handling of your payment is covered by Stripe's own privacy policy.

App store codes

Some leagues include the MahWins app for their new members. If you join one of those on the web with a new account, we email you a one-time App Store or Google Play code and keep a record of the code, the email it went to and whether it was delivered, so we can resend it or answer a question about it. Redeeming the code happens with Apple or Google under their terms.

Third-Party Services

We use a small set of outside services to run MahWins:

  • Resend โ€” delivers transactional email (verification codes, password resets, invitations, claim offers, league setup and plan emails, and app store codes).
  • Apple Push Notification service (APNs) โ€” delivers push notifications on iOS.
  • Firebase Cloud Messaging (FCM) โ€” delivers push notifications on Android. Operated by Google.
  • Sign in with Apple โ€” optional authentication. Operated by Apple.
  • Sign in with Google โ€” optional authentication. Operated by Google.
  • DigitalOcean โ€” hosts our API, database, and uploaded photos.
  • Stripe processes league plan payments. Stripe sees the email you give at checkout, the plan and league name, and your payment details, which never reach us.

These providers process only what's needed to do their job (for example, Resend sees the email address and message body; APNs/FCM see the message title and body for any push you receive) and are bound by their own privacy terms.

Cookies and Local Storage

The MahWins app does not use cookies. On the web (mahwins.com), we keep it minimal:

  • The group dashboard stores your sign-in token in your browser's local storage so you stay logged in. It is required for the dashboard to work and is never used to track you. Signing out clears it.
  • We use no advertising or analytics cookies anywhere on the site.
  • If you choose to sign in with Google or Apple on the web, their sign-in tools load only after you tap to use them, and those tools set their own cookies under Google's or Apple's control. We do not load them until you opt in. See Google's and Apple's privacy policies for how they handle that.
  • If you buy a league plan, the organize page keeps the league name you typed in your browser's session storage while you are at Stripe, so the welcome step can use it; it is gone when the tab closes. Stripe's checkout page sets its own cookies under Stripe's control.

How We Use Your Information

  • To provide core app functionality โ€” logging games, computing stats, photos, groups, friends, notifications
  • To authenticate requests and keep your account secure
  • To send you account-related messages (verification codes, password resets, and push notifications you've enabled)
  • To diagnose and fix bugs
  • To prevent abuse (rate limiting, blocks, review of reports)
  • To run leagues: keep rosters and standings for organizers, show the standings pages they create, and process plan purchases

We do not sell your data, share it with advertisers, or use it to train machine-learning models.

Data Retention and Deletion

  • Your account and data are kept as long as your account is active.
  • You can delete your account at any time from the app's Settings screen. Deletion suspends the account immediately and signs you out of all devices. Logging back in within 30 days reactivates it; after that, the account and all associated data (games, photos, group memberships, push tokens, friend links) are permanently removed.
  • Refresh tokens expire after 30 days; expired tokens are purged daily. JWT access tokens expire after 15 minutes. Verification and password-reset codes expire after 15 minutes.
  • Group invitations that have been accepted or declined are removed after 90 days. Pending invitations stay until they're acted on.
  • Photo files no longer referenced by any game or avatar are removed by a daily cleanup job (with a one-hour grace period to avoid race conditions during uploads).
  • Failed-login records are cleared automatically on a successful sign-in.
  • Abuse reports you submit are stored as long as your account exists so we can review patterns of repeat offenders. Operational logs (request, error, authentication, email/push delivery, and rate-limit logs) are kept for as long as needed to operate and secure the service; we don't sell or share them.
  • A player an organizer added by name is kept while their league keeps them. Once they claim their games, or the group is deleted, the placeholder is retired and anonymized after 30 days, the same way a deleted account is.
  • Public standings pages stay online until the organizer turns them off, replaces the link, or deletes the group.
  • Purchase records and Stripe identifiers are kept as long as we need them for accounting and tax purposes.
  • App store code records are kept so we can resend a code or answer a question about it; the codes themselves expire on the store's schedule.

Your Rights

You can access, correct, export, or delete your data at any time. Most changes can be made in the app (display name, color, avatar, password, stats visibility, blocks, account deletion). For anything else, email support@mahwins.com.

Security

All data in transit is encrypted over HTTPS. API requests are authenticated with short-lived JWT access tokens (15-minute lifetime) backed by longer-lived refresh tokens stored on your device in the OS's secure keychain/keystore. Refresh tokens are hashed on the server โ€” we can revoke a session but we can't read the token itself. We restrict production access to a small number of engineers and rotate credentials regularly. When you ask us for help with a league, a MahWins staff member may open your group with the same view an organizer has; every such access is logged.

Children

MahWins is not directed at children under 13 and we don't knowingly collect information from them. If you believe a child has created an account, please contact us and we'll remove it.

Changes to This Policy

If we update this policy we'll change the "Last updated" date above and, for material changes, notify you in the app or by email.

Contact

Questions? Email support@mahwins.com.

โ† Back to home ยท support@mahwins.com ยท Terms ยท Accessibility