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.

3 min readUpdated 26 August 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 only while baseUrl is https://. The app does not validate the scheme, and nothing stops a configuration pointing at http://. 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.

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 No Push subscription removed

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.

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
CryptoCompare News requests, carrying the device's IP and the API key in the client Proxy this through your backend if you can — the key is quota-bearing and a client-side key is a shared quota
vectorlogo.zone, via.placeholder.com Nothing but the request itself — decorative images The request still discloses your customer's IP to a third party. Consider bundling the assets instead

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.

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.