MMashDiv

Data safety and privacy

The Play Data safety declaration and the iOS privacy answers, derived from what the app actually transmits — every data type, where it goes, whether it is shared, and what account deletion does and does not remove.

4 min readUpdated 26 September 2026mobile, data-safety, privacy, gdpr, kyc, play-console

Google Play requires a Data safety declaration and Apple requires App Privacy answers. Both are made by you, about your deployment, and both must match what the binary actually does — a declaration that understates collection is treated as a policy violation rather than a mistake.

This page is the raw material, traced from the app's own source. It is not a substitute for reading your own configuration: several answers below depend on which addons you have licensed.

Encryption in transit is yes because a release build refuses to start unless baseUrl is https:// and wsBaseUrl is wss:// — it opens on its Configuration Error screen instead. Debug and profile builds still accept http:// and ws:// for local testing, so publish only a release build. Your server's certificate is still yours to keep valid. Data retention depends on which addons you run — the table's deletion column describes the platform's behaviour, not your legal obligations.

What the app collects

Everything below goes to your own backend unless the Shared column says otherwise. Nothing is sent to an analytics, advertising or crash-reporting service, because the app bundles none — no Firebase Analytics, no Crashlytics, no Sentry, no ad SDK. The only Firebase components in the app are Firebase Core and Cloud Messaging, for push notifications, and they do nothing unless you add your own Firebase project.

Play data type Collected Required Purpose Shared Deleted with the account
Personal info — Name Yes Yes Account management No Yes, nulled
Personal info — Email Yes Yes Account management, security No Yes — tombstoned to deleted-{id}@deleted.invalid, and the address is released for re-registration
Personal info — User IDs Yes Yes Account management, fraud prevention No Username nulled; sign-in provider links hard-deleted
Personal info — Phone Yes No Account management, 2FA No Yes, nulled
Personal info — Address Yes Per flow Fulfilment (store), legal compliance (KYC) No Order records retained; KYC address retained
Financial — Payment info Yes No Payments Yes — Stripe Not held by you
Financial — Other financial info Yes No App functionality, fraud prevention No (P2P method details are shown to the counterparty) Transactions retained
Financial — Purchase history Yes No App functionality No Retained
Photos and videos Yes No KYC, dispute evidence, support No KYC documents retained
Files and docs Yes No KYC, dispute evidence No Retained
Messages — other in-app messages Yes No App functionality, support Shown to the counterparty in P2P chat Tickets and messages retained
App activity Yes No App functionality No Mixed
Device or other IDs Yes No Push delivery If you configure push, Google's Firebase Cloud Messaging issues the device's push token and delivers to it — see the third-party table below. The app also sends your backend a device ID of its own: a keyed hash of the account's user ID and a random secret that is made on the phone and never leaves it, so it differs for each account on a phone Push tokens in the account's settings removed; the backend's device record (device ID, push token, platform) is retained

Location is not collected. The P2P country/region/city on an offer is typed by the user, not read from the device, and there is no location permission in the manifest. Do not declare Location.

Contacts, calendar, audio, health and web browsing are not collected.

Card payments go to Stripe, not to you

Fiat deposits open Stripe's own PaymentSheet. The card number, expiry and CVC are entered inside Stripe's native UI and travel directly from the device to Stripe — your backend only ever sees a clientSecret and a paymentIntentId. Declare payment info as collected and shared with a third party, and name Stripe.

KYC is the sensitive one

Play classes identity documents as personal and sensitive information, and this is where the app handles the most of it.

  • What is captured: front and back scans of an identity document plus a selfie holding it. The stock document types are passport, driver's licence, national ID and residence permit — but the KYC form is server-driven, so the exact fields are whatever your levels define.
  • How it travels: the file is base64-encoded into a JSON body (not multipart) and posted to /api/upload/kyc-document. The server validates the magic bytes, caps the decoded size at 10 MB, and stores it privately — not under a public uploads path.
  • EXIF is not read. The picker is called with requestFullMetadata: false, and images are downscaled to 2048×2048 at quality 85 before upload.
  • No permission is requested for the gallery. Android capture routes through the system Photo Picker, so the app never declares READ_MEDIA_IMAGES and you never have to answer Play's Photo and Video Permissions declaration.
  • It is retained after account deletion, deliberately, because AML record keeping requires it. Say so in your privacy policy.

What account deletion actually does

The in-app deletion is not a soft flag. Inside one transaction it anonymises the record: email tombstoned, and password, phone, avatar, username, wallet address, profile and settings nulled; sign-in provider links are hard-deleted. The email address is released, so a deleted customer can register again.

What it does not remove: transaction and order records, KYC documents and the identity data on them, and support tickets and their messages. Those are retained by design. Your privacy policy has to say this — "we delete everything" is the answer that is not true.

The backend's record of each phone registered for push (its device ID, push token and platform) is not removed either. The app signs out straight after a deletion and deletes the push token on the phone as it does, but the server no longer has a session to revoke that record with, so it stays.

Third parties the app contacts directly from the device

Most traffic goes to your backend. These do not:

Host What reaches it Why it matters
Stripe Card data, during a fiat deposit Declared as shared; Stripe's own privacy policy applies
Google Sign-In The sign-in exchange, only if you enable it Ships disabled in the packaged config. It is on when googleAuthEnabled is true, or when that key is absent and googleServerClientId is set
Firebase Cloud Messaging (Google) The device's push token, only if you configure push The token is a device identifier held by Google. Account for it in your Data safety and App Privacy answers, and in your privacy policy, whenever push is on

News is not on this list. The app reads market news from your own server (/api/news), which fetches from the providers you configure; the phone holds no news key and calls no news provider. Coin logos and uploaded images are loaded from your own server's address, or from whatever absolute address your server hands the app for them.

The iOS side

ios/Runner/PrivacyInfo.xcprivacy ships with the app and is wired into the Runner target's Copy Bundle Resources phase. It declares no tracking, an empty tracking-domains list, and two required-reason APIs (user defaults, file timestamps). Read the comment at the top of that file before changing it — it explains which reason codes apply to the app rather than to a plugin, and why three other categories are deliberately absent.

It also declares twelve collected data types, each linked to the user, none used for tracking, and all for app functionality: email address, name, phone number, physical address, user ID, device ID, payment info, other financial info, photos or videos, customer support, other user content, and other data types. Your App Store Connect answers start from that list; check it against the addons you actually run and anything you have added to the app.

Apple aggregates your manifest with every bundled framework's. Google Sign-In's own manifest declares coarse location, a device ID and usage data for analytics; that is Google's collection in Google's bundle, and your App Store Connect answers still have to account for it.

One thing to fix on your own deployment

The app puts the user id in the WebSocket query string rather than only in a header. Query strings are logged by proxies and reverse proxies as a matter of course. It is an internal identifier rather than a credential, but if you run access logging on your own edge, that is where it will accumulate.