Version 1.0 · Effective: 30 August 2026
Data controller: grAppe, Colombia — grappestudio@gmail.com Contact: grappestudio@gmail.com
Pulso is a free app that displays public rainfall, river-level, air-quality, weather and mobility information for the Aburrá Valley (Medellín, Colombia). This policy explains what data the app handles, why, and what choices you have.
This is a translation. The Spanish (Colombia) version at https://grappe-studio.netlify.app/pulso/privacy.html governs in case of any discrepancy.
Pulso has no accounts and no sign-up. There is one feature through which you can send us information, and you always start it yourself.
From Settings → Send a suggestion or report a bug (also available in the Information tab) you can write to us. Before sending, the app shows you exactly what will be sent, with the real values, in an expandable block called "What gets sent".
Sent:
Not sent, deliberately:
Because no identifier is sent, we cannot tell which reports are yours, nor link them to you or to each other. That is intentional, and it has a consequence worth stating plainly: we also cannot retrieve or delete a specific report on your request (see section 8).
To prevent abuse, our server momentarily processes the IP address a report arrives from, solely to limit how many messages one origin can send. That address is not stored with the report; it becomes a one-way hashed value that changes daily and is discarded within hours.
Reports are kept for at most 400 days (see section 7).
If you voluntarily email grappestudio@gmail.com, we process your address and message solely to reply to you.
Pulso uses Firebase services from Google LLC, acting as our data processor.
When the app crashes or logs an error, a report is sent containing the stack trace, device model, OS version, app version, memory and disk state, and a Firebase-generated installation identifier.
We attach three of our own keys so a crash can be reproduced: the active map layer (layer), the app version (app_version) and the device language (locale).
Purpose: fixing bugs. Legal basis: legitimate interest in keeping the app working.
App start time, screen rendering time and network request durations, with technical device and network data — all collected automatically by the SDK.
Pulso adds two traces of its own, which measure only durations:
| Trace | What it times |
|---|---|
layer_time_to_data | how long a map layer took to show its data, tagged with which layer and whether the data came from the network, the on-device cache, a bundled file, or was already loaded |
siata_refresh | how long one full data refresh took |
Neither carries anything you typed, and neither carries your location.
This is covered by the same switch as usage analytics — Settings → Privacy → "Compartir estadísticas de uso" turns off performance collection too, including the automatic part described above.
Purpose: detecting slowness and failing requests.
Pulso logs 47 events of its own. None of them contains anything you typed, and none contains your location or anything derived from it.
| What it measures | Events |
|---|---|
| Which layer or screen you are looking at, and for how long | layer_switch, layer_dwell, slot5_swap, bar_expand, screen_view, settings_open, info_open, alerts_open, splash_complete |
| What you tap on the map | callout_open, map_sample, radar_play, radar_scrub, radar_jump_live, radar_expand, forecast_slot_change, air_submetric_change, bike_intent_change, bus_route_select, metro_line_reveal, transit_list_toggle |
| Whether the data actually loaded, so we can tell "all clear" from "we had no data" | refresh, data_outcome, overlay_empty, notice_shown, layer_hidden_remote, rc_unknown_layer_key |
| How long things took | request_timing, layer_time_to_data |
| Whether alerts reach you and are useful | alert_banner_shown, alert_navigate, alert_dismiss, alert_pref_change, push_open, push_suppressed, push_permission |
| Permissions and preferences | location_primer_shown, location_result, home_zone_set, setting_change |
| App health and the version gate | info_link_tap, diagnostics_open, feedback_open, feedback_submit, update_required_shown, update_required_tap, review_prompt_requested |
Two of these deserve to be spelled out, because they are the ones you would reasonably worry about:
home_zone_set records only how a municipality was chosen — from a location fix or from the list. It does not record which municipality. Nothing derived from your location is ever attached to an analytics event.feedback_submit records only that a message was sent and whether it succeeded. It never contains the message.request_timing records how long one request to a public data source took. The address is reduced to a pattern first — any query string is discarded and any digits are replaced — so it identifies the endpoint, never a specific request, and cannot carry a token.We also attach a small number of user properties to this install so the numbers can be read by segment: your appearance, temperature and units preferences, whether notification and location permission are granted, whether a home municipality is set (a yes/no, never which one), and which map layer this install uses most.
You can turn all of this off. Settings → Privacy → "Compartir estadísticas de uso". It is on by default, and switching it off stops Firebase Analytics collecting anything at all from this install, including the automatic events described in the next paragraph. Crash reports (§3.1) are separate and stay on, so that a crash you hit can still be fixed.
You should also know that the Firebase Analytics SDK itself collects, on its own and as standard, automatic events (first open, sessions, app update), device characteristics, and an approximate country- or region-level location derived from the IP address — not from GPS. That inference is made by Google, not by Pulso, and it does not give Pulso your location.
Events are associated with a Firebase app instance identifier. It is not linked to your name, email or any account, and it is reset if you uninstall and reinstall the app.
Purpose: understanding which parts of the app are used, to decide what to improve.
The app periodically fetches server-side configuration (which layers to show, whether there is a maintenance notice, whether alerts are enabled). The request transmits the installation identifier and technical device data. Nothing about your usage is sent.
Pulso's alerts are topic broadcasts: the device subscribes, and the server publishes one message to all subscribers.
This has a deliberate consequence in your favour: Pulso does not store, transmit or keep any record of your device identifier. There is no device database, because topic delivery does not need one.
The topic name depends on what you choose on the Alerts screen:
alerts_v1_river;alerts_v1_river_envigado.⚠️ You should know what that implies. Pulso does not receive this, but the subscription is made with Firebase Cloud Messaging (Google), so Google can tell that this device listens for river alerts in a particular municipality. That is the price of your phone not ringing for alerts from the far end of the valley. If you would rather avoid it, save no places: with none saved the device subscribes only to the valley-wide topic, which says nothing about where you are.
Your operating system generates a notification token (FCM on Android, APNs on iOS) that stays on the device. It appears only in internal development builds, on the Information screen, so that a test notification can be sent by hand; copying it is an action you take, never an automatic one. Released builds do not show it on any screen.
In released builds, iOS uses Apple's App Attest to certify to our server that a request comes from a genuine copy of Pulso rather than a script. It is a cryptographic device check; it does not identify a person.
This section describes the only way Pulso can use your location.
What happens. The app may ask permission to take one position fix. On iOS this happens when you tap "Use my location" on the Alerts screen, and when you open the app on the forecast if permission was already granted. On Android it happens the first time you open the forecast, if you allow it. If you grant it, the app requests one position fix, compares it against the municipal boundaries bundled with the app, obtains the zone name — envigado, say — and discards the coordinate immediately.
Why iOS repeats it on open. Because a saved municipality goes stale: someone who moved, or who once tapped another municipality on the map out of curiosity, kept seeing that forecast forever even with location permission granted. Each reading replaces the last — they do not accumulate, none is stored, and none leaves the phone. What you choose by hand, in the picker or by tapping the map, wins for the rest of that session: your location does not argue with you.
If you do not grant permission, no municipality is selected. The app does not guess one, and it does not keep one it inferred from an earlier reading: the forecast opens with no municipality and the line "Selecciona un municipio primero" until you choose. One you picked by hand is kept, because it is not a guess.
What is kept: the zone name, on the device. What is never stored or transmitted: the coordinate, the altitude, the accuracy, the speed, the time of the fix, or any history. It is not attached to an analytics event, a crash report or a suggestion.
There is no continuous tracking. The app uses no background location, no geofences, no region monitoring and no significant-change updates. It asks for one reading, turns it into a name, and stops.
You can avoid it entirely. The same screen lets you pick places from a list of thirteen zones with no permission granted, and it works exactly as well on both platforms.
In Apple's privacy declaration this is declared as Precise Location, not Coarse Location, even though the app requests hundred-metre accuracy: that figure is a hint to the system, not a cap, and Apple requires declaring the most granular data the code could receive. On Android the app requests ACCESS_COARSE_LOCATION (approximate only), so the Play Data Safety form declares Approximate location.
Never transmitted anywhere, and removed when you uninstall the app:
envigado,bello — never as coordinates. You pick them from a list; on both platforms you may also use your location once to fill one in, and only the resulting zone is kept (see 3.7). ⚠️ The list itself never leaves the device, but it determines which notification topics the device subscribes to: see the warning in 3.5.On Android, backups are disabled (allowBackup="false"), so none of the above is uploaded to Google Drive.
Pulso fetches data straight from the public sources. When it does, those servers receive — as in any internet request — your device's IP address and technical connection information. Pulso sends them nothing else.
| Server | What for | Operated by |
|---|---|---|
siata.gov.co, geoportal.siata.gov.co | rain, radar, river levels, air quality, weather | SIATA / Área Metropolitana del Valle de Aburrá |
www.metrodemedellin.gov.co | Metro stations and lines | Metro de Medellín |
www.datos.gov.co | open datasets | Government of Colombia |
api.citybik.es | EnCicla stations and bike availability | CityBikes (private provider) |
| Google/Firebase services | analytics, crashes, config, notifications | Google LLC |
| Google Maps SDK (Android only) | the base map | Google LLC |
| MapKit (iOS only) | the base map | Apple Inc. |
These third parties handle that data under their own policies, which we do not control:
Pulso has no official relationship with SIATA, the Área Metropolitana del Valle de Aburrá, Metro de Medellín or EnCicla. It uses their public data with attribution.
Firebase processes and stores the data described in section 3 on Google servers outside Colombia, primarily in the United States. Google relies on standard contractual clauses and the applicable transfer frameworks. By using Pulso you accept this transfer, which is necessary for the crash-reporting and analytics services to function.
Under Colombia's Law 1581 of 2012 and Decree 1377 of 2013, you have the right to know, update, rectify and delete your personal data, to request proof of the authorisation given, to be informed about how it has been used, to complain to the Superintendencia de Industria y Comercio, and to revoke your authorisation.
If you are in the European Economic Area or the United Kingdom, you also have the GDPR rights of access, rectification, erasure, restriction, portability and objection.
An honest caveat about exercising them: Pulso holds no data that identifies you, so in practice we cannot locate "your" data within analytics or crash reports, even if you ask. By design, it is anonymous with respect to you. What you can do, with immediate effect:
For any request or question: grappestudio@gmail.com. We reply within fifteen (15) business days, as required by Law 1581.
Pulso is not directed at children under 13 and does not knowingly collect their data. There is no user-generated content, no messaging and no in-app purchases.
All app connections use HTTPS. The app stores no credentials. Administrative access to the Firebase project is restricted and protected with two-factor authentication; the database rules permit only public read access to a single service-status document and deny all writes from clients.
No system is perfect: we cannot guarantee absolute security of any internet transmission.
If this policy changes materially, we will publish the new version at https://grappe-studio.netlify.app/pulso/privacy.html with an updated effective date and — where the change warrants it — announce it inside the app. Continued use after the effective date constitutes acceptance of the revised version.
grAppe Colombia grappestudio@gmail.com