DRAFT, have it reviewed by a lawyer. Last updated: 27 October 2026. Fill in the placeholders in square brackets. Evidence and open questions: docs/legal/README.md.
Christian Maag
Gleißelstetten 129/1, 89081 Ulm, Germany
E-mail: support@cinesofa.de
This policy applies to the Android app CineSofa (phone, tablet, Android TV).
CineSofa is a media player for playlists you add yourself. The app contains no ads, no analytics or tracking tools and no third-party crash-reporting services. We do not sell data. There is no user account with e-mail or password.
Without device pairing, most data stays on your device only, including playlists, provider logins, profiles, kids approvals, watch history and settings. Android backup is disabled. Only the features listed below transfer data.
Your provider login data (username and password) is stored locally in the app's own database on the device. There it is not encrypted; the password is stored in plain text. In addition, a copy of the login is kept in the app's encrypted storage (Android EncryptedSharedPreferences). The database is accessible only to the app on devices that are not rooted, and it is not backed up. Provider logins are not synced. They leave the device only for an optional provider transfer (see below): then they are encrypted and sent via the Firebase Realtime Database for at most 5 minutes.
When you use an M3U playlist or Xtream login, the app connects directly to your provider's servers. Streams, channel lists and images come from those servers. Your provider technically receives your IP address and your login. We have no control over those servers and do not receive this data.
On first launch the app creates a random device identifier (e.g. "dev_…"). It is not a hardware or advertising ID. It is stored locally and sent to our server function (Google Cloud Functions) on every app start. The function uses it to check whether the 6-day free trial is running or the app is unlocked. If the device is paired, the app also sends the room ID; the function uses it to check whether the device belongs to the room and, if needed, adds a device that was already paired before the change to the room's device list (see "Pairing and syncing devices"). We store the identifier and the time of first launch.
Purchases (yearly subscription or one-time purchase) are handled exclusively by Google Play. Only Google processes payment details; we never receive them. When you buy, the app gives Google only a check value (SHA-256) of the room ID instead of the room ID itself. It then sends Google's purchase token, the product, the room ID and the device ID to our server function. The function verifies the purchase through the Google Play Developer API, acknowledges it with Google and binds it to the room if the device belongs to the room. At app start the app also compares the purchases tied to your Google account with Google Play and reports them the same way.
For each purchase we store in Cloud Firestore: a check value (SHA-256) of the purchase token (the token itself is not kept there), the ID of the room the purchase unlocks, the check value of the room ID taken from the purchase, product, type (subscription or one-time), purchase status, for subscriptions the expiry date, the order number, whether it is a test purchase, whether the purchase was acknowledged, and the times of creation, change, binding and re-binding. Google notifies us of changes (renewal, cancellation, refund); we keep the message ID of these notifications for about 8 days so that they are not processed twice. If Google refunds a purchase that is not yet assigned to a room on our side, we keep only the check value of the purchase token and the time (about 40 days) so that the purchase does not unlock anything after the refund. We keep the purchase token itself only temporarily: if a purchase still has to be acknowledged with Google, the token sits in a server-side queue (no access from the app) until Google has accepted the acknowledgement, at most 4 days, and is then deleted.
A purchase belongs to the room, not to a person. A purchase can be moved to another room, at most once every 30 days. If you run "Delete sync data", the room ID is removed from the purchase record; the rest of the record remains and can be bound to a new room.
For pairing, sync and provider transfer, the app signs in anonymously with Google Firebase Authentication. This creates a random user ID with no link to your name or e-mail.
When the sign-in expires, the app uses the Google Play Integrity API to check that it is an unmodified copy from Google Play running on a genuine device. Google Play creates a check token on your device. Our server function has Google evaluate it and only receives the result: whether the app is licensed and whether the device passes the integrity check. The result is not stored permanently. To prevent replay attacks we keep a hash of the one-time number for at most about 70 minutes.
When you pair devices (by code or QR code), the app creates a shared "room" in the Google Firebase Realtime Database (location: Belgium, EU). The room stores:
The parental PIN and provider logins are not synced; the PIN applies only to the device it was set on.
The app syncs profiles and kids approvals when you pair a device on first launch (profiles only), when you open the home screen or the profile picker, create or delete a profile, and when you open or save the kids selection. There is no continuous live sync. On the first sync the app uploads the existing profiles or the kids profile's previous approvals, afterwards only changes.
The room can only be reached with its random, unguessable room ID. A room holds at most 3 devices; rooms that already had 4 devices keep them. After the first 3 devices, at most 2 new devices can be added per 30 days.
Our server function enforces these limits. For this it stores in Cloud Firestore, per room, the device identifier, device model name and joining time of each device, the number of devices that have joined so far and, for 30 days, which device left the room or was newly added and when. It removes older entries the next time the room changes. Per device it also stores which room the device belongs to; this entry is deleted when the device is removed. For rooms that existed before the change, it keeps a cut-off list of room and device identifiers so these devices keep their room, until all these devices have been migrated, at the latest twelve months after the date of this policy. Storage location: EU (Firestore multi-region eur3).
The pairing code itself is stored encrypted for 5 minutes. It is deleted immediately when redeemed; an unredeemed code is removed by automatic clean-up at the latest about one hour after it expires.
Pairing only works within the same home network. When the code is shown, the server stores the device ID of the showing device and a check value (SHA-256) of the room ID and the network part of your public IP address (IPv4 the first three blocks, IPv6 the first 56 bits), never the address itself, and compares it with the check value of the redeeming device. Both are deleted as soon as the code is redeemed, otherwise at the latest about two and a half hours after the code was shown. Purpose: the license covers one household (Art. 6(1)(b) GDPR). Storage location: EU (Firestore multi-region eur3).
You can send a provider login (name, type, address, username, password) to another device using a code. The data is encrypted with a key derived from the code and stored in the Firebase Realtime Database for at most 5 minutes. It is deleted as soon as it is retrieved, otherwise at the latest about one hour after expiry. Provider logins are not synced permanently.
When you open the detail page of a movie or series, the app requests ratings from MDBList (mdblist.com). It sends the public movie ID (TMDB or IMDb ID), the media type, our app key and, for technical reasons, your IP address. No other information about you or your account goes to MDBList. Results are cached on your device.
The app contains a list of movie facts (genres, runtime, director, cast, release year, title). The list comes from Wikidata (wikidata.org, public domain under CC0 1.0) and ships with the app. The app matches it against your catalogue on your device only. Nothing is transmitted, and no data about you is created.
The app can translate English descriptions into German on your device. The texts never leave your device. The required language model (about 30 MB) is downloaded once from Google servers, over Wi-Fi only. Google technically receives your IP address in the process. According to Google, ML Kit may also send technical usage and performance data to Google.
The app computes recommendations, for example under "For you", on your device only. They are based on each profile's viewing history, favourites and your thumbs ratings, from which the app derives preferences for genres, cast, directors and decades. Thumbs ratings stay on the device and are not transmitted, not even when syncing; the preferences are only computed for display. We do not receive this data.
The camera is used only when you scan a QR code, for example for pairing. Images are analysed on the device only and are neither stored nor transmitted. You can revoke the permission at any time in Android settings.
Under Settings > Support & Feedback > Help you can check your device and report a problem. If the app crashes, it stores a crash report locally on your device (app version, device model, Android version, time, technical stack trace; logins are masked).
Check connection: The app checks network, clock, provider access and licence on your device and shows matching tips. It only asks our server service for the server time and calls your provider with your login to test access. If you answer a tip with "Yes" or "No", we only count which tip helped (a counter per tip and day, without a device ID). To limit requests, the server briefly stores a counter with a hash of your anonymous sign-in.
Report a problem: When you choose "Report a problem", you see before sending a summary of what will be sent (diagnostic package). Only when you tap "Send" do we transmit it to our server service in Belgium (europe-west1). The package contains app version, device model, Android version, device ID, sync room ID (if paired), licence status, the result of the self-check, the latest technical error events and the head and stack trace of a crash (the preview shows only a short version of it). Web addresses and logins are masked beforehand as far as they can be recognised; playlist addresses, channel names, watch history, profiles and child approvals are not intended to be included. Free text and error messages may still contain names or details we do not recognise. We transmit your provider's server name separately and only encrypted (TLS); the server immediately turns it into a shortened check value (HMAC) and discards the name. The check value only serves to detect outages at a provider across several devices. In addition there are the category and the text you write yourself. Please do not put logins or addresses in the text. After the report has been created successfully, the locally stored crash report is deleted.
Continue on your phone: Instead of typing on the TV you can scan a QR code. For this the report with the diagnostic package is already created when the code is generated; if no text arrives within 30 minutes, it is handled without your text. The QR code leads to cinesofa.de/hilfe. The one-time code is in the part of the address after the "#" and is therefore not sent to the web server; it is valid for 30 minutes. Your text goes from there to the same server service. The page is delivered via Firebase Hosting (Google). We limit wrong codes per network; for that we store a shortened, hashed value of the IP address for at most one hour.
Handling by us, with AI support: We see your ticket in our control centre. In addition, an AI service prepares a draft reply: Claude models by Anthropic (Claude Haiku 5.5 for sorting, Claude Sonnet 5.5 for the draft) via Google Cloud Vertex AI, processed in the EU (multi-region eu). The AI receives your text, the previous course of the ticket, short details of up to 5 earlier reports of your device (category, status, beginning of the text), the cleaned diagnosis including the device designation (manufacturer and model), whether your trial has already been extended, and a summary of the sorting step. Device and room IDs, device names you assigned, provider names and web addresses are not passed to the AI; other devices in your room appear only as "Device A/B/C". The AI decides nothing on its own: a person reads every draft, edits it if needed and sends the reply. Measures such as a trial extension are carried out by a person only and only work in your favour. Replies from support are marked in the app as "Created with AI support".
My requests: Under Settings > Help > My requests the app retrieves the tickets that belong to your sign-in and device and shows our replies. You can reply there and say whether the answer helped.
Per device and per sign-in at most 3 reports per day and 10 per month are possible; in addition there is a daily limit for devices without a passed device check. The counters contain the device ID in plain text and are deleted after about one month.
When you tap "Trailer", the app opens the YouTube app or your browser with a search for the title. From then on, Google/YouTube's terms and privacy policy apply.
We do not share data for advertising.
Some Google services (Cloud Functions, Firebase Authentication, Play Integrity, ML Kit) may process data in the USA. Google LLC is certified under the EU-US Data Privacy Framework (European Commission adequacy decision of 10 July 2023). The EU Standard Contractual Clauses in Google's data processing terms also apply. For MDBList only the title identifier (TMDB/IMDb) and, for technical reasons, your IP address are transmitted, possibly to the USA; there is no safeguard under Art. 46 GDPR for this. The e-mail provider IONOS processes e-mails within the EU.
You have the right to:
You can withdraw any consent at any time with effect for the future. You may also lodge a complaint with a data protection supervisory authority, in particular in your country of residence, e.g. the State Commissioner for Data Protection and Freedom of Information of Baden-Württemberg (LfDI BW).
The app is not directed at children under 16. Kids profiles are a feature for adults to restrict content. If sync is used, the name, approvals, watch progress and favourites of a kids profile are stored encrypted in the sync room (see above).
We update this policy when the app or the law changes. The version published in the app and at https://cinesofa.de/datenschutz applies.
Privacy questions: support@cinesofa.de
Christian Maag, Gleißelstetten 129/1, 89081 Ulm, Germany