Privacy Policy
TapNomad is built so that we know as little about you as possible. The app has no user accounts, no advertising, no third-party analytics SDKs and no tracking. This policy explains the little that remains.
1. Who we are
TapNomad is operated by Rabotto, a sole trader registered in Finland (business ID 3646938-8) (“we”, “us”). We are the data controller for the processing described here.
Contact for privacy matters: privacy@tapnomad.app
2. The short version
- No account. You never register, and we never learn your name or email.
- Your location answers your own requests, nothing else. The app uses it on the phone to show where you are and to guide you to a water point. When you ask for the nearest place or nearby water points, your coordinates are sent in that one request so our server can answer it; they are not stored, and we keep no history of them.
- No advertising, no trackers. The app contains no ad networks and no third-party analytics SDKs. Anonymous usage counters exist only if you opt in, go only to our own servers, and cannot identify you (see 3.4).
- Purchases are handled by Apple. We never see your payment details.
- Content requests are anonymous. When the app fetches water-quality data or map tiles, our servers see a normal internet request (IP address, requested content), as every server on the internet does, and nothing more.
- One exception, and only for Premium downloads. Offline packs are not public files: to download one, the app asks our server for permission and sends a random identifier created by your own app installation, plus the anonymous subscription id from RevenueCat. That is how we check the subscription and stop one copy of the app from downloading our whole database. Neither identifier is tied to you (see 3.3).
3. What data is processed, and why
3.1 Location
If you grant location permission, the app uses your device’s location to show your position on the map, provide route guidance, and find the nearest place and water points.
- Position display, route guidance and working out which country you are in before a download over mobile data happen on your device.
- When you tap “Use my location” or view nearby water points, the app sends your coordinates in that one request to our server, which answers it and does not store them. We keep no history of where you have been. The coordinates travel in the request body, never in the request address, so they do not appear in our hosting provider’s request log either.
- The app remembers your last map position on the device only, so the map reopens where you left it. It is never uploaded.
- The permission is optional: search and all water-quality information work without it.
- You can revoke the permission at any time in your device settings.
Legal basis: consent (the operating system permission), GDPR Art. 6(1)(a).
3.2 Content requests (server logs)
When the app loads water-quality data, map tiles or offline packs, your device makes requests to our infrastructure: a Supabase database in the United States (AWS us-east-1) and Cloudflare storage and CDN (bucket location: eastern North America). What is stored there is water-quality data and map content — nothing about you.
Like every web server, that infrastructure necessarily processes your IP address and the content you requested, and the providers keep short-lived operational logs for security and reliability. We do not use those logs to identify or profile anyone, and we keep no per-user history of the places you looked at.
To keep the service available for everyone, our API also keeps short-lived request counters (rate limiting): each counter is keyed by a salted cryptographic hash of the caller’s IP address, the raw address is never stored by us, and the counters are deleted within an hour. They are used for nothing except slowing down abusive traffic.
Because these providers are outside the EEA, that transient log processing is a transfer to a third country. It happens under each provider’s data processing agreement incorporating the European Commission’s Standard Contractual Clauses.
If you ask for a map, we count the place, not you. Tapping “Ask for this map” on a destination we do not cover yet sends us that place’s name, on its own. There is no identifier attached, so we can count that a place was asked for a hundred times and still have no way to know whether that was one person or a hundred. We keep a running tally per place, plus when it was first and last asked for and when we delivered it, so we can tell how quickly we respond. Your device remembers which places you asked for, so the button can say “Asked”; that list stays on the phone.
Offline pack downloads are the one authorized request. The water-quality database is what this service is, and it used to be downloadable by anyone who guessed a file name. Pack files now live in private storage, and the app has to ask our server for a short-lived, single-file permission before each download. That request carries a random identifier your app installation created for itself, the anonymous RevenueCat app-instance identifier, and the name of the pack you are downloading. We record one row per granted pack (identifier, a subscription key our server derives from what RevenueCat reports about the purchase, pack name, timestamp) purely to enforce a daily and monthly download limit and to cut off a leaked subscription; the rows are deleted after 31 days. The identifier is not your device id, not an advertising id and not tied to your identity: it is created inside the app, it exists only in that install, and deleting the app destroys it.
Legal basis: legitimate interest in operating a secure, functioning service and in protecting our database against bulk extraction, GDPR Art. 6(1)(f); for the entitlement check itself, performance of a contract, GDPR Art. 6(1)(b).
For the curious: every request the app can make, exactly
This is the complete list of network requests the app makes, with everything they carry. There are no others.
searchwithq— the city or country you typed, sent to our server to find matches. Not stored, not counted.searchwithlon,lat— your coordinates, when you tap "Use my location", to find the nearest covered place. Answered and discarded.refillwithlon,lat,limit— your coordinates, when the map asks for nearby water points (withlayer=shops, for nearby shops that likely sell bottled water). Answered and discarded.- The three requests above carry their values in the request body, not in the request address, because our hosting provider's request log records addresses and never bodies.
answer/<city>— the city page you opened, by its public name.- Map tiles — plain file downloads from our CDN; the request names the tile, nothing
about you. The same is true of
offline/manifest.json, the public list of which packs exist and how large they are. download-token— asks for permission to download one offline pack. Carries three things: the random identifier your installation created for itself, the anonymous RevenueCat app-instance identifier, and the pack name. Premium only. Our server records a subscription key derived from what RevenueCat reports about the purchase (the store, the subscription's original purchase date and the date the app was first obtained from that store account), not the identifier itself. Answered with links that carry your installation's identifier and a signature and expire in 10 minutes. Within those minutes the link itself is the key: anyone holding it could fetch that one file, which is why the app never shows or shares it.- Offline pack files themselves, from
downloads.tapnomad.app, each with the link above in its address. Without a valid link the file is not served to anyone. Request logging is switched off on that service, so the identifier in the address is not kept there. events— the opt-in anonymous counters of section 3.4. Sent only with your consent, in batches; contents listed below.request-pack— sent only when you tap "Ask for this map" on a place we have no offline map for. It carries the name of that place and nothing else: no identifier, no coordinates, not even your app language. We count how many people asked for each place so we build the most-wanted maps first.- One call to your phone's own geocoding service (Apple or Google, not us) when a location lookup finds no covered place and the counters are on — described in 3.4.
- Purchase receipts to Apple and RevenueCat, section 3.3. Crash reports to Sentry only with the separate consent of section 3.6.
3.3 Purchases (Premium subscription)
Premium subscriptions are sold through Apple’s App Store. Apple processes your payment; we never receive your name, card number or billing address. Our subscription processor RevenueCat assigns an anonymous, randomly generated app-instance identifier when the app starts, and uses it with the purchase receipt to activate your subscription across reinstalls. Neither carries your identity.
Legal basis: performance of a contract, GDPR Art. 6(1)(b).
3.4 Anonymous statistics (opt-in)
If you turn on Share anonymous usage and reliability stats (off by default), the app counts a small, fixed set of events: the app was opened, a city page was viewed, a lookup or search found no data, an offline pack was downloaded or failed to download, an answer was served from an offline pack, guidance started, arrived, fell back or was reported blocked, a Premium subscription was active, and a server request failed. Each count carries only the event name, at most a city name, the app language and the platform (iOS/Android), and is stored as a daily total in our own database, with no user identifier, no device identifier, no IP address and no time more precise than the calendar day. When a location lookup finds no covered place near you, the app asks your phone’s built-in geocoding service (Apple on iOS, Google on Android) for the name of the city you are in and counts that name, so we know where coverage is missing; your coordinates go only to that system service, never to us, and this too happens only while the toggle is on. There is nothing to link to a person, no third party receives it, and we use it for exactly two things: deciding which cities need better data, and finding where the app fails. Counters are deleted after 24 months. Turn the toggle off at any time to stop immediately; anything not yet sent is discarded.
Legal basis: consent, GDPR Art. 6(1)(a).
For the curious: every counter, exactly
Each stored row is calendar day + event name + label + app language + platform → count. The label ("slug") is listed per event; where none is listed, the event has no label at all. This is the complete set — the database rejects anything else.
app_open— the app was opened.city_opened— a city page showed an answer. Label: the city.answer_unknown— a city page had no verdict. Label: the city.search_no_result— a text search found nothing. No label: what you typed is never sent.nearest_no_place— "Use my location" found no covered place. Label: the city name from your phone's geocoder, e.g.fi-jarvenpaa. Never coordinates.pack_downloaded/pack_download_failed— an offline pack finished or failed. Label: the pack.offline_answer_served— an answer came from a downloaded pack. Label: the city.nav_started,nav_arrived— guidance started / reached the water point.nav_fallback— routing was not possible and guidance fell back to compass mode. Label: the technical reason, e.g.no_path.route_broken_tap— you tapped "Route blocked?".premium_active— a subscription was active, at most once per open.api_error— a server request failed. Label: the endpoint and status class, e.g.answer_5xx.
3.5 Data stored only on your device
The app keeps its working data locally on the phone: your language and theme choices, whether you have completed onboarding and opted in to anonymous statistics, the last five places you opened, your last map position, downloaded offline packs, the countries where you allowed downloads over mobile data, and a local navigation log used for troubleshooting. None of it is uploaded, and deleting the app deletes all of it.
For the curious: everything on the device, exactly
- Preferences: language, appearance (light/dark), avoid-stairs, and the two consent toggles (anonymous stats, crash reports).
- A flag that onboarding was completed.
- The last five places you opened (name and verdict, for the Recents list).
- Your last map position, so the map reopens where you left it.
- Downloaded offline packs (map tiles, water data, walking network) and a local copy of the pack catalog, so the offline screens work with no network.
- For a city that downloads in several parts, which of its cities you picked it by, so the Downloaded list names it the way you did.
- The subscription state RevenueCat last reported, so Premium works offline.
- The places you have asked for an offline map for, so the button can say "Asked" instead of inviting the same tap again.
- The countries where you allowed offline downloads over mobile data (country codes only), so the app asks once in each country. Offline maps lists them and can clear them.
- For the App Store rating request: the day the app first gave you a verdict, how many verdicts you have seen, and the app version and day it last asked. The request itself is Apple's own sheet; whether you rate, and what, never passes through us.
- A random identifier this installation created for itself, used only when asking permission to download an offline pack (3.2). It is generated on the device, never derived from anything about your phone, and it goes with the app when you delete it.
- A technical event log (two files, 512 KB each, newest overwrites oldest) recording app events such as "route computed" for troubleshooting on your device. Coordinates are refused at the writing layer, so it cannot contain locations.
3.6 Diagnostics (opt-in crash reports)
By default the app sends no crash reports or diagnostics; error information stays on your device. If you turn on Crash reports in Privacy & consent, the app sends an anonymous report when it crashes or hits an error, so we can fix it. A report contains the error and stack trace, your device model, operating system version, app version and app language. It never contains your location (coordinates are actively stripped before sending), your searches, or anything that identifies you; the app has no identifiers to send. Reports go to our error-reporting processor Sentry, stored in the European Union (Germany) and deleted after at most 90 days. You can turn the toggle off at any time, which stops reporting immediately.
Legal basis: consent, GDPR Art. 6(1)(a).
For the curious: what a crash report contains, exactly
- The error message and stack trace (which line of our code failed).
- Device model, operating system version, app version and build.
- The app's last technical steps before the crash ("breadcrumbs"): which of our server endpoints were called and with what HTTP status. Query strings are stripped before sending, so these can never contain coordinates or search text.
- What it does NOT contain: no user or device identifier (the app has none), no IP address stored with the event, no location (coordinate-shaped fields are deleted before sending), no searches, no account of any kind.
4. What we do NOT do
- We do not sell, rent or share personal data — we have essentially none to share.
- We do not use advertising identifiers (IDFA/AAID) or cross-app tracking.
- We do not fingerprint devices or profile users.
- We do not use cookies in the app.
- We make no automated decisions about you.
5. Data recipients (processors)
| Processor | Role | Location / safeguards |
|---|---|---|
| Supabase | Database and API hosting for water-quality content; answers nearest-place requests that carry your coordinates transiently (nothing stored); authorizes Premium pack downloads and keeps the 31-day download counters | United States (AWS us-east-1); data processing agreement with EU Standard Contractual Clauses |
| Cloudflare | Storage and delivery of map tiles and offline packs (no personal data stored; request logging off on the pack download service) | Bucket in eastern North America, served from Cloudflare’s global network; data processing addendum with EU Standard Contractual Clauses |
| RevenueCat | Subscription activation: anonymous app-instance identifier and purchase receipt. Our server also asks RevenueCat whether that identifier has an active subscription before authorizing an offline download | Data processing agreement; no identity data |
| Apple | App distribution and payment | Apple’s own terms and privacy policy apply |
| Sentry | Crash reports, only if you opt in | Stored in the EU (Germany); data processing agreement with EU Standard Contractual Clauses |
All processors act under data processing agreements and only on our instructions.
6. Data retention
- Location: coordinates in a nearest-place request are processed to answer that request and are not stored; they travel in the request body, which the server logs below do not record. Your last map position lives only on your device.
- Server logs: retained by our infrastructure providers for a short operational period (days to a few weeks) and then deleted.
- Purchase records: retained as long as your subscription is active and thereafter as required by bookkeeping law.
- Crash reports (if you opted in): deleted after at most 90 days.
- Anonymous usage counters (if you opted in): daily totals only, deleted after 24 months.
- Offline download records (Premium only): one row per granted pack, deleted after 31 days.
- Map requests: a per-place tally with no identifier, kept while the place is uncovered and as a record of how quickly we delivered it.
7. Your rights (GDPR)
You have the right to access, rectify and erase personal data concerning you, to restrict or object to processing, to data portability, and to lodge a complaint with a supervisory authority (in Finland: the Data Protection Ombudsman, tietosuoja.fi). Because we hold practically no personal data, most requests will result in the honest answer “we have nothing about you” — but we will always verify and respond. Contact: privacy@tapnomad.app.
8. Children
TapNomad does not target children, contains no age-inappropriate content and collects no personal data from anyone, including children.
9. Changes to this policy
We will update this page when the app’s data practices change (for example if opt-in diagnostics are added) and revise the effective date. Material changes will be highlighted in the app’s release notes.