PROGRESSION RACING LEAGUE

Privacy Policy

How Progression Racing League (“PRL”, “we”, “us”) collects, uses and protects your personal data when you use the PRL app or website.

Effective date: 2026-05-11

Version: 2026-10-16

1. Who’s responsible

Progression Racing League is operated by Jonathan Baagø, a sole proprietor based in Denmark. Jonathan is the data controller under EU Regulation 2016/679 (GDPR) for all personal data described below.

We do not currently have a designated Data Protection Officer because our processing operations do not meet the Art. 37 GDPR triggers. The controller acts as the single point of contact — see Contact.

2. What we collect, why, and on what legal basis

Identity and account

DataPurposeLegal basis
Email address, password (hashed), display name, profile photo, language, location, short bioIdentify you, sign you in, render your profile, attribute your race resultsGDPR Art. 6(1)(b) — performance of contract
Your Zwift ID, if you choose to link itMatch Zwift race results to your PRL accountArt. 6(1)(b)

Consent records

DataPurposeLegal basis
Record of when you accepted these Terms and this Privacy Policy, version strings, IP address at the timeDemonstrate consent was given under Art. 7 GDPRArt. 6(1)(c) — legal obligation

League activity

DataPurposeLegal basis
Race signups, stage line-ups, stage results, season standings, jersey results, team rostersRun the league: pair you to races, calculate standings, settle results disputes, render the public standingsArt. 6(1)(b) + Art. 6(1)(f) — legitimate interest in keeping league history intact

Zwift data (from ZwiftPower and ZwiftRacing.app)

DataPurposeLegal basis
Your ZwiftPower category, your ZwiftRacing.app rating (vELO) and how many races you rode in the last 90 days, read for your checked Zwift ID, with the date and the site each number came fromShow you, your team (its riders and staff) and league admins your current category and rating without you typing themArt. 6(1)(a) — consent, given when you link your Zwift ID; withdraw it in one tap under Settings → Zwift account (that deletes what we read)
The same category and rating, shown to everyone in the league — only if you switch "Show my category and rating to the whole league" on (off by default)Let other teams see your level, for example when you are looking for a teamArt. 6(1)(a) — a separate consent; switching it off hides them from other teams at once
Your FTP and weight as ZwiftPower shows them — only if you switch "Power numbers" on (off by default)Let you and your current team's staff see your FTP and W/kgArt. 6(1)(a) — a separate consent; switching it off deletes the numbers at once
Your finishing place in ZRL rounds your team races, from the ZwiftPower results page of the eventShow your places on the round page, in the season grid and in your historyArt. 6(1)(f) — legitimate interest in keeping the team's ZRL record; riders who are not on PRL are shown only as "Not on PRL"
A name you ask us to look up on Zwift ("Is this you?") and up to five Zwift riders we found for itHelp you find and link your Zwift IDArt. 6(1)(b) — you asked for it; deleted after 24 hours

Once your Zwift ID is checked, PRL reads your public ZwiftPower category and ZwiftRacing.app rating about once a week so your team sees them here. FTP and weight are read only if you switch that on. You can switch it all off under Settings → Zwift account. ZwiftPower and ZwiftRacing.app are sources we read from, not processors of your data: we send them nothing about you but your Zwift ID. A number is always shown with the site and the date it came from, and nothing here sets a price or a value on you.

Live race data

DataPurposeLegal basis
During a race you start in: your power, W/kg, heart rate, cadence and draft, about once a second, and a W′ balance estimate worked out from your power — only if you switch "Share live race numbers with my team" on (off by default). Your position and gaps are the team's race and are shown without it.Let your team's race staff — the DS and the captain (whoever holds race calls) and that race's road captain — follow the race live and call it; you see your own numbers on your race screenArt. 6(1)(a) and, for heart rate, Art. 9(2)(a) — your explicit consent, given with the switch; withdraw it with the same switch
One summary per race: average / normalised / max power, average and max heart rate, average cadence, the lowest W′ balance, time in five zones, distance, duration and your finishing placeLet you and your team's race staff look back at a raceArt. 6(1)(a) / Art. 9(2)(a) — the same consent; kept only for races you rode while sharing

Live race data is off unless you switch it onin Settings → Training data (“Share live race numbers with my team”). While it is on, your numbers go only to your own team’s race staff for the race you are riding, and to you. The live frames are never stored: they are passed on and forgotten. One short summary per race is kept for 12 months. Switching it off works immediately— from the next live update your team sees only your position, never your body numbers again — and you can still read your own summaries. Nothing here is ever shown on a public page, a stream overlay or Discord.

Training data (Intervals.icu)

DataPurposeLegal basis
If you connect Intervals.icu: daily fitness, fatigue and ramp rate; per activity its date, type, name, duration, distance, power, training load, intensity, FTP and heart rate (average and max); your best power for 1 s to 1 hShow you your training; only if you also switch on sharing: your PRL fitness and fatigue come from it (everyone in the league sees those two numbers) and your team's officers see your training, including heart rateArt. 6(1)(a) and, for heart rate, Art. 9(2)(a) — explicit consent at connect, and a second one for sharing; disconnecting deletes your key and everything copied

Your team’s public page

DataPurposeLegal basis
Your display name and two-letter country on your team's public web page — only if your team turned its public page on AND you said yes under Privacy & Data → Public team page (off by default)Show who rides for the team to anyone with the page's link (it is on the open internet)Art. 6(1)(a) — your consent; switching it off removes your name from the page at once. Nothing else about you is ever on that page

Communications and social

DataPurposeLegal basis
Direct messages, shoutbox posts, forum threads, polls, news posts, moderation actionsLeague-internal communication, team coordination, abuse preventionArt. 6(1)(b) + Art. 6(1)(f) for moderation
Voice channel metadata (who joined when, per-user volume settings). Voice traffic itself is not recorded.Real-time voice during racesArt. 6(1)(b)
If you link Discord: your Discord user id and name; while you are in your team's Team Radio or Radio 1:1 channel, that you are there, muted or deafened, and — while a DS has the live cockpit open — whether you are talking (no audio is ever recorded, listened to or stored)Show your team and league staff who is "on radio" on My Team and on race dayArt. 6(1)(f) — legitimate interest in running team radio; on unless you switch "Show me as on radio to my team" off in Settings → Mail & Discord

Payments (post-banking launch)

DataPurposeLegal basis
Stripe customer ID, payment metadata, subscription / contract / transfer recordsProcess payments, settle transfers, prove contractual obligations, comply with Danish bookkeeping lawArt. 6(1)(b) + Art. 6(1)(c) — Danish bogføringsloven §10, 5-year retention

AI-assisted features

DataPurposeLegal basis
Prompts you trigger from AI-assisted features (e.g. the post-race "coach take" button): the action you ask for plus the small set of race numbers it summarises (race name, finishing position, points). We never send your messages, DMs, or contact list.Generate the requested summary or coaching text via a large language model hosted on PRL infrastructure. Each call is logged with token counts so we can enforce a per-rider burst rate limit.Art. 6(1)(b) — performance of contract (you triggered the feature). Your prompt and the generated reply never leave PRL infrastructure.

AI-assisted features (e.g. the post-race “coach take” button) use a large language model that runs on PRL-owned infrastructure. There is no third-party AI sub-processor— your prompts and the generated replies never leave our servers. Only the small numeric context you triggered (race name, finish position, points) is fed into the model; we never forward your messages, contact list, or browsing history. Each rider is capped by a short-burst rate limit enforced server-side.

Notifications

Push notification tokens from your device, your notification preferences, and a 90-day log of notifications sent to you. Used to deliver in-app and push notifications. Legal basis: Art. 6(1)(b) for in-app, Art. 6(1)(a) consent for push (you can mute any category in Settings).

Pre-launch waitlist

If you sign up on the home page to be notified when the public beta opens, we store your email, a record of when you ticked the consent box, and a hash of your IP (kept 30 days for abuse triage). We send you a one-time confirmation email; you’re only added to the list once you click the confirm link. Every email contains a one-click unsubscribe link. Legal basis: Art. 6(1)(a) consent.

Operational

Audit logs of selected actions, rate-limit counters, data-export job records. Used to keep the league secure and to fulfil your Art. 15 access rights. Legal basis: Art. 6(1)(f) legitimate interest in security and abuse prevention.

3. How long we keep it

Different categories of data have different retention rules. We keep data no longer than necessary for the purpose it was collected for, in line with Art. 5(1)(e) GDPR.

CategoryRetention
Identity + accountLifetime of your account, then 30-day grace, then erasure
Consent records3 years after your account is erased
Race historyIndefinite while you have an account; pseudonymised on erasure
Financial records5 years from the end of the financial year (Danish bookkeeping law)
Direct messages24 months from last activity, then archive 12 months, then permanent delete
ShoutboxFeature retired on 2026-09-30: its remaining data is archived, access-locked, and deleted before public launch
Team chat, forum and pollsRetired on 2026-09-30 (moved to Discord): the remaining data is archived, access-locked, and deleted before public launch
NotificationsLeague mail: 180 days after its last update (starred mail until you unstar it); message alerts: 90 days. Alerts of the chat features retired on 2026-09-30 are archived, access-locked, and deleted before public launch
Moderation logFeature retired on 2026-09-30: its remaining data is archived, access-locked, and deleted before public launch
Audit logIndefinite (security forensics)
Voice metadataIn-app voice retired on 2026-09-30 (voice now runs on Discord): the remaining metadata is archived, access-locked, and deleted before public launch
Zwift data (category, rating, FTP / weight if shared)While your Zwift ID is checked and you have not switched it off; each earlier reading 12 months. Switching it off, or losing the check, deletes the current numbers at once
ZRL places of riders not on PRLTheir Zwift ID and ZwiftPower name 30 days at most (or until they join and are matched), then only the anonymous place
"Is this you?" lookups24 hours
Live race numbers (heart rate, power, W′ balance)Never stored: each frame is passed to your team's race staff and forgotten
Live race summaries12 months, then deleted; kept only for races you rode while sharing
Intervals.icu training dataWhile you stay connected; disconnecting deletes your key and everything copied
Your name on a public team pageWhile both you and your team keep it switched on; removed at once when either switches it off
Discord radio presenceWho is in a radio channel: 10 minutes at most, and at once when you opt out or unlink; "talking" is never written down
Pre-launch waitlistUntil you unsubscribe or beta opens + 30 days, then erased

These rules are enforced by automated nightly jobs — there is no manual step where someone forgets to delete things. The one exception is the in-app features we retired on 30 September 2026 when chat and voice moved to Discord (shoutbox, team chat, forum, polls, moderation log, voice): their remaining data is kept in an access-locked archive that no app user can reach, is still covered by your data export and erasure rights, and is deleted in full before public launch.

4. Who else sees it

Your data lives in our systems and the systems of the third-party processors below. We sign a Data Processing Agreement (DPA) with every processor before they handle any production data, and we never sell or rent personal data to anyone.

ProcessorWhat they touchRegion
SupabaseDatabase, authentication, file storage, edge functionsEU Ireland (eu-west-1)
ResendTransactional email (verification, password reset, etc.)EU (Ireland)
CloudflareDNS, captcha (Turnstile), DDoS protection, edge CDN for this siteGlobal edge with EU presence
PostHogProduct analytics (pseudonymous unless signed in)EU (Cloud EU region)
LiveKit (self-hosted)Real-time voice. On our own equipment — not a third party.Denmark
Apple APNs / Google FCMPush notification delivery (when you opt in)Global (their infrastructure)
Stripe (post-banking)Payments. Added once payments go live.EU residency configured

We may also disclose your data when required by Danish or EU law (for example: a court order, a tax investigation under the bookkeeping retention rules, or a lawful request from Datatilsynet).

5. International transfers

All primary processing is within the European Economic Area. Apple APNs and Google FCM may receive your push token outside the EEA; both providers have their own EU adequacy or Standard Contractual Clauses in place. When Stripe is enabled, EU customer-data localisation will be configured before any production traffic flows.

6. Your rights

Under GDPR Articles 15–22, you have the right to:

All requests are free of charge and we’ll respond within 30 days as required by Art. 12(3). If a request is manifestly unfounded or excessive (e.g. a flood of duplicate requests), we may charge a reasonable fee or refuse — and we’ll tell you which and why.

7. Security

8. Cookies and similar tech

This website uses only essential cookies (none currently — this site is fully static). The PRL app stores a session token locally so you stay signed in across launches.

Product analytics (PostHog) uses a pseudonymous identifier in local storage. You can opt out via your device’s “Limit Ad Tracking” / “Reset Advertising ID” setting; we honour those signals.

9. Changes to this policy

If we change this policy in a material way (new categories of data, new processors, new lawful bases), we’ll notify you in-app and by email and ask you to acknowledge the new version before the change takes effect. The version string at the top of this page bumps for every change.

10. Complaints

If you think we’re handling your data unlawfully, please contact us first — most complaints can be resolved that way. You also have the right to lodge a complaint directly with the Danish supervisory authority:

Datatilsynet
Carl Jacobsens Vej 35, 2500 Valby, Denmark
Phone: +45 33 19 32 00
Email: [email protected]
Web: www.datatilsynet.dk


Reviewed and last published 2026-05-11. Last operational changes reflected: GDPR data-export feature live; auth flows protected by captcha; retention purges automated; PII split into a separate table with admin-only access.