Version 1.4 · Effective: 19 October 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/es/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). For problems with alerts we also attach counts — how many alerts are shown, set aside or not yet sent, and how many zones you saved, never which ones — any setting the app could not recognise, and, when joining a notification topic failed, that topic without its zone (e.g. alerts_v2_river_zone).
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 59 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, 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 |
| Whether sharing, the alerts reminder and the home-screen widget are used | share_app, alerts_promo_shown, alerts_promo_action, widget_open |
| Which hazards the data put on screen, how the alert carousels and the warning button are used, and which notifications you choose | alert_active, alert_carousel_shown, alert_carousel_swipe, alert_button_open, alert_panel_close, push_received, push_setting_change, push_scope_change, alert_place_change |
Three 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.alert_place_change records only how your list of zones changed (added, edited, removed) and how many zones are saved. It never records which zone, and never the name you gave it.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), how it was set (by your location, from the list, by tapping the map, the Medellín Centro example, or none; never which one), whether a Pulso home-screen widget is installed (a yes/no), which map layer this install uses most, which kinds of alert you chose to be notified about (for example river rises and earthquakes), whether those notifications cover your zones or the whole valley, and how many zones you saved (a number, never which). On Android, Google Play tells Firebase how Pulso was installed: from the store itself, or the source, medium and campaign of the link that led there (for example a link on our website).
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's servers never receive, store or keep any record of your device identifier. There is no device database, because topic delivery does not need one.
The topics depend on what you choose in Settings → Notifications. Notifications are off until you switch a hazard on: until then alerts appear only inside the app, and the device is subscribed only to one general topic that every copy of Pulso shares, kept for exceptional announcements. Then:
alerts_v2_seismic. Metro has one topic per line, e.g. alerts_v2_metro_a, and its switch subscribes to all of them;alerts_v2_river; with "My zones only", one topic per zone saved under "My zones", e.g. alerts_v2_river_envigado, and none while no zone is saved;alerts_v2_general while any hazard is on.⚠️ You should know what that implies. Pulso does not receive this, but the subscription is made with Firebase Cloud Messaging (Google), so with "My zones only" Google can tell that this device listens for flood alerts in particular municipalities. That is the price of your phone not ringing for alerts from the far end of the valley. If you would rather avoid it, choose "Whole valley": the device then subscribes only to the valley-wide topic, which says nothing about where you are.
To receive topic messages, the app obtains a notification token from your operating system (APNs, on iOS) and from Firebase Cloud Messaging (FCM, on both platforms). That token is sent to Google, because FCM needs it to deliver the messages of the topics the device is subscribed to; Pulso's servers never receive it. The app obtains it whether or not you have allowed notifications, so that alerts work as soon as you allow them. 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 two ways Pulso can use your location: to find your zone, and to show where you are on the map.
When permission is asked for. On its own, the app asks only once: a few seconds after the forecast appears on screen, if it has never asked before, on Android and iOS. In addition, while it is not granted, Settings shows a location row: "Use my location" opens the system request and, if you already refused, "Turn on in phone settings" takes you to Pulso's page in the phone's settings. It can also be asked for, on both platforms, by tapping "Use my location" while adding or editing a zone (Settings → Notifications → My zones).
Your zone. With permission granted, the app takes one position fix each time it starts, and another right after you grant it. It compares that fix against the municipal boundaries bundled with the app, obtains the zone name (envigado, say) and discards the coordinate immediately.
Why it is repeated at start-up. 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 saved. The app does not keep one it inferred from an earlier reading. A few seconds after the forecast appears it shows Medellín Centro as an example, so the forecast strip describes a real place: that example is never saved, anything you choose replaces it, and neither the home-screen widget nor alerts use it. One you picked by hand is kept, because it is not a guess.
Your position on the map. With permission granted, every map shows where you are as a blue dot, with a lighter circle for how accurate the fix is and a cone for the direction the phone is facing. The direction comes from the phone's compass, which needs no permission of its own. To keep the dot current, the operating system updates the position while the app is open on screen; the updates stop when the app goes to the background. The position is only drawn: it is not stored, not sent anywhere, does not move the map, and is not used for the zone.
What is kept: the zone name, on the device. What is never stored or transmitted: the coordinate, the altitude, the accuracy, the speed, the compass direction, the time of any fix, or any history. None of it is attached to an analytics event, a crash report or a suggestion.
There is no tracking. The app uses no background location, no geofences, no region monitoring and no significant-change updates. For your zone it asks for one reading, turns it into a name, and stops; the map's dot lives only on screen, and nothing it shows is kept.
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. Without permission the maps simply show no dot.
In Apple's privacy declaration this is declared as Precise Location, not Coarse Location, even though the zone reading 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_FINE_LOCATION together with ACCESS_COARSE_LOCATION, so the system dialog lets you choose precise or approximate, and the Play Data Safety form declares Precise location.
Never transmitted anywhere, and removed when you uninstall the app:
envigado), never a coordinate. Unlike the zone on the map, tapping the map does not change it.envigado,bello), never as coordinates, each with the name you may give it ("Home", "Mum's house"). 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 and its names never leave the device, but with "My zones only" the zones determine 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
The pages under https://grappe-studio.netlify.app/pulso/ count visits with Google Analytics 4 (Google LLC, acting as our processor), and only if you accept the banner shown on your first visit. Nothing is set or sent before you choose, and nothing at all if you decline.
If you accept, Google Analytics sets its cookies (_ga and _ga_ followed by an identifier), limited to the /pulso/ pages and kept for about 13 months, and records the pages you view, how you arrived (a search engine, another website, a shared link), an approximate region derived from your IP address, your browser and device type, and clicks on links that leave the site, such as the App Store and Google Play buttons. Advertising features and Google signals are switched off. This data is kept for 14 months, and it is not linked to the app or to any app install.
Your choice is stored only in your browser. You can change it at any time from the Cookies link at the bottom of every Pulso page; withdrawing your consent deletes those cookies.