Finance Privacy Policy
The short version
Finance is an app for tracking personal and family finances. We keep your data on our own server so that it syncs between your devices and between the members of a shared space.
The most important things on one screen:
- We don't show ads, don't sell data and don't embed a single tracker or analytics system. There are none in the code at all.
- We can see your financial records: amounts, dates, accounts, categories, notes, receipt contents. They sit in our database in ordinary (not separately encrypted) form — that is how any app works that calculates your reports on a server.
- If you have invited someone into a shared space, they see ALL the transactions of that space, not just the "shared" ones. There is no "this one is only mine" filter in the app.
- A photo of a receipt is sent to an external artificial-intelligence service for recognition (currently Google Gemini). We don't store the photo itself, but it does leave our server.
- Your profile photo is served over a direct link with no password and no sign-in: whoever has the link will see the photo.
- A bank connection gives us the right to read your statement only. The app is technically incapable of transferring, debiting or paying out your money.
- There is currently no password recovery: we don't send any emails at all. A forgotten password cannot be recovered.
What follows is the same thing, in detail. Every statement on this page has been checked against the source code of the app and the server.
Who is responsible for your data
The controller (under the GDPR) and the owner of personal data (under Ukraine's personal data protection law) is Serhii Pashchenko, a natural person, Poland, postal address: 31-356, Poland.
To get in touch about any data question: support@serhiip.dev. This is the only address at which we accept requests; we have no others.
This policy applies to:
— the Finance mobile app for iPhone (in the App Store — Finance);
— the mobile app for Android (Finance, identifier com.serhiipashchenko.capital);
— the server that runs them, including the addresses https://finance.serhiip.dev and the legacy address https://91-99-155-40.sslip.io, which remains hard-coded in previously released builds of the app.
Effective date of this version: 16 September 2026.
What data we receive and store
Account
— Email address. It is your login and the only way we can identify you. We don't confirm it by email (we don't send any emails from the app at all).
— The name you entered in your profile. It signs your records in a shared space.
— Password — only as an irreversible hash (argon2). We neither store nor see the password itself.
— Profile photo, if you uploaded one (up to 6 MB, png/jpeg/webp/heic/heif). It sits directly in our database.
— Appearance settings (theme, colour scheme, tab accents, app icon) and interface language — so that they match on all your devices.
Financial records — the core of the app
— Accounts: name, type, currency, current balance, the "savings" flag, archived/favourite status.
— Transactions: amount, currency, rate against the base currency, date, type (expense, income, transfer), account, category, your free-form note, a split across several categories.
— Categories, category groups and savings goals (how much, by what date).
— Budgets and the monthly plan: how much is assigned and how much is spent in each category.
— Subscriptions you track: name, amount, period, next charge date.
Receipts
— What we save from a receipt: the shop, the date and time of purchase, the currency, the total, the fiscal number, the original contents of the QR code and the line-by-line list of items — the name, quantity and price of each item.
— What we do NOT save: the photo of the receipt itself. It lives only in the server's memory for the duration of the request and is not written down anywhere.
— We also remember rules of the form "this item → this category", so we don't ask you twice. These rules are shared across the whole space.
Bank connections
— The personal Monobank token you pasted in, or the request identifier at a European aggregator. These secrets are encrypted in the database with AES-256-GCM.
— What comes from the bank and is saved: the bank's account numbers/identifiers, balances, currency, card type and transactions — amount, date, currency and payment description. A bank transaction description often contains the name of a shop or counterparty; with Polish banks, the account name may include the account holder's name and the last 4 digits of the IBAN.
— What comes but is NOT saved: the bank customer's name, the full IBAN, the masked card number, the transaction's MCC code. Our code simply doesn't read these fields.
Sessions
— For every sign-in we keep a session row: your identifier, an irreversible hash of the refresh token (the token itself is not in the database), the expiry date and a revocation flag.
Technical
— We do NOT store your IP address. It is used only in the server's memory as a rate-limiting counter (protection against password guessing) and never reaches the database. Our database does have columns for IP and device type, but the code writes nothing into them — they are always empty.
— We don't keep an HTTP request log. The server logs contain only application startup, cache errors, background-job warnings and the error text from the receipt recognition service.
What we don't collect at all
Verified by searching the entire code of both apps and the server:
- No usage analytics or statistics: no Firebase, no Google Analytics, no Amplitude, no Mixpanel, no Segment. The iOS project has no external libraries at all.
- No crash reporting: no Crashlytics, no Sentry, no Bugsnag.
- No advertising and no advertising identifiers: we don't request the IDFA, don't show the App Tracking Transparency prompt, don't read the Android Advertising ID. In our App Store listing, the "Data Used to Track You" section honestly says "none".
- No location. There is no location permission either in the Android manifest or in the iOS project. What's more, the GPS tag from a receipt photo goes nowhere: the image is re-compressed before sending, and the EXIF is lost in the process.
- No access to contacts, calendar, microphone, health, SMS or calls.
- We don't read other apps' notifications and we don't parse your email. The screens with such names in the Android version are unfinished stubs with no code behind them; we will remove them.
- We don't request access to your whole photo library. You pick a specific file in the system picker, and the app receives only that file.
- There are currently no push notifications at all — neither via Apple nor via Firebase. Accordingly, there are no push tokens either.
- We don't collect payment data: there are no in-app purchases and no payment libraries in the code.
- We don't sell data and don't pass it to advertisers or data brokers. The complete list of addresses our server contacts at all is given below — there are no others.
One honest caveat: this is the result of a line-by-line review of the source code and the dependency lists, not a formal audit of the compiled binary.
Why we need this data and on what legal basis
A contract with you (Art. 6(1)(b) GDPR) — without this data the app simply doesn't work:
— email and password hash: so that you can sign in;
— accounts, transactions, categories, budgets, subscriptions: the bookkeeping itself, the reports and the plan;
— space membership: to decide whose data to show to whom;
— sessions: so as not to make you type your password every 15 minutes.
Your consent (Art. 6(1)(a)) — you switch this on yourself, and can switch it off at any time:
— the camera and receipt photos, including sending the image to an external recognition service;
— connecting a bank and regularly reading the statement;
— connecting to the Polish state hub for electronic receipts;
— the profile photo;
— inviting another person into a shared space.
Our legitimate interest (Art. 6(1)(f)):
— rate limiting and protecting sign-in against password guessing;
— minimal technical logs, so that we can fix breakages;
— storing session hashes, so as to spot a stolen token and break the session chain.
The law (Art. 6(1)(c)) — when we are obliged to answer your rights request or a lawful request from an authorised body.
A separate word about sensitive data. The category of an expense can say more about you indirectly than the amount does: a purchase at a pharmacy or a payment to a clinic is about health, a donation is about beliefs. We don't collect such data deliberately and don't draw any conclusions about you from it, but it inevitably ends up in the app together with receipts and transactions. If this matters to you — don't connect receipt recognition, and enter such expenses manually under a general category.
Automated decisions and profiling
We don't take automated decisions about you that would have legal or similarly significant effects for you. There is no scoring, no creditworthiness assessment and no "the algorithm decided" refusals in the app.
We have exactly one piece of automation: suggesting a category for an item from a receipt. It works from a dictionary, from your past decisions and — when the corresponding key is enabled on the server — from a language model's suggestion. It is always only a suggestion: you change any category by hand with a single tap, and the app will remember your choice.
Who sees your data
You. In a personal space, only you see the data (and we, as the owner of the server — technically it is accessible to us, and we don't pretend otherwise).
Members of a shared (family) space. This is the most important thing to understand before you send an invitation.
When a person accepts an invitation, they see:
— all transactions of the space — amounts, dates, currencies, accounts, categories and your free-form notes, including the payment descriptions imported from your bank with the names of shops and counterparties;
— all accounts and their current balances;
— all budgets, the plan and subscriptions;
— all receipts with the line-by-line contents of the purchases: in which shop, when, for how much and exactly which items;
— the summary reports "what we buy most often" and "what is about to run out", compiled from the purchases of all members;
— who exactly entered each record: the author's name and profile photo are shown next to the transaction;
— the email address of every member of the space.
There is no "this expense is visible only to me" mode in the app. Separation by author inside a shared space does not exist on any screen. If there are expenses you don't want to show — keep them in your personal space.
The profile photo — over a direct link, without sign-in. Your avatar is served at an address of the form /api/users/<your identifier>/avatar with no password and no authorisation: that is how the apps themselves load it. This means that anyone who has this link will see the photo without logging in to Finance. The identifier is random and cannot be guessed, but it is legitimately visible to all members of your shared spaces. The response is marked as cacheable for a year, so even after you delete the photo, copies already downloaded may remain for some time in the caches of browsers and intermediate servers. If this is unacceptable to you — don't upload a photo; your initials are shown instead.
An invitation link discloses part of the data before sign-in. The invitation preview page opens without authorisation and shows: the name of the space, the name of the person who invited you and — if the invitation is addressed to a specific person — the email address of the person being invited. Forward the invitation code only to the person it is meant for.
Us. Serhii Pashchenko has access to the database — technically, in order to run the server. We don't read your transactions out of curiosity and don't use them for anything other than operating the service.
Bank connections: we read, but we don't pay
Finance can connect to a bank so that you don't have to enter transactions by hand.
What we can do: read the list of your accounts, their balances and the statement — the amount, date, currency and description of each transaction.
What we CANNOT do: make a transfer, pay for anything, debit money, change limits or do anything else with your money. For the Monobank token we use, only the right to read the statement and customer data has been requested, and the European connection works through a licensed aggregator in "account information only" mode. There is not a single payment-creating request in our code. Even if we wanted to — the app has no such function.
How the access is stored: the bank secret (your personal Monobank token or the request identifier at the aggregator) is encrypted in the database with AES-256-GCM, using a key kept separately from the database.
How often we contact the bank: a background sync job contacts the bank regularly for as long as the connection is active. Disconnect the bank in the app and the requests stop.
Important: disconnecting the bank does NOT delete the accounts and transactions already imported. This is deliberate, so that you don't lose your history. If you want to get rid of the data as well — delete the account or the transactions manually; deleting an account also deletes all of its transactions.
There is one more way transactions can get into the app: Monobank can send us notifications about new transactions on a connected account. This is read-only as well — money cannot be moved by such a notification.
Receipts: what happens to the photo
There are two ways to enter a receipt.
1. By QR code. The app reads the QR and asks the fiscal operator that issued the receipt for its contents. In this case only the receipt identifier from the QR code goes out (for receipts from the online office of the tax service of Ukraine — the entire address from the QR as it is written there). No photo is sent anywhere.
2. By photo. If there is no fiscal QR, the photo of the receipt goes from our server to an external recognition service — currently the Google Gemini model. It is given the whole image and the instruction text "extract the shop, the date, the total and the list of items". Neither your name, nor your email, nor your account identifier is added to this request — but the receipt itself usually shows the name and address of the shop, the date, the time and the full list of purchases. This is probably the most sensitive data transfer in the whole app: a pharmacy receipt reveals far more than the line "Pharmacy, UAH 240".
What happens to the photo on our side: it is not saved. The file lives only in the server's memory for the duration of the request; there is not a single field for a receipt image in the database, it is not written to disk and it does not end up in the logs. Only the recognised text goes into the database: shop, date, total, list of items.
What happens to the photo at the recognition service: that is governed by the service's own terms, not by our code. We cannot guarantee that it does not use the images it receives according to its own rules.
If this doesn't suit you — don't use photo recognition. Scanning a fiscal QR and manual entry work without any transfer of images.
Separately: if the additional auto-categorisation key is enabled on the server, the names of unrecognised items and the list of your category names are sent to Anthropic (USA). There is no name, email or account identifier in that request. In our current server configuration this path is switched off.
Polish electronic receipts. If you have connected the state hub for electronic receipts of the Ministry of Finance of Poland, we regularly ask it for your receipts, passing the identifier issued to you (KID). The private part of the KID is stored encrypted on our side and is not given out to anyone except the hub itself; the public part is the one you show the cashier as a barcode.
Who we pass data to
The complete list — there are no other recipients in the code.
- Hetzner Online GmbH (Falkenstein, Germany) (Germany, EU) — hosting. Our entire database physically sits on its servers: accounts, all financial records, receipts, profile photos, encrypted bank secrets, cache and logs. The hosting provider doesn't look into the data; it provides the hardware.
- Google (the Gemini API service) — recognition of a receipt from a photo. Receives the whole image of the receipt. Processing happens on Google's global infrastructure, which means outside the EU as well.
- Anthropic (USA) — fallback auto-categorisation of items: item names and the names of your categories. Enabled only through a separate server setting; currently switched off.
- Monobank (Ukraine) — if you have connected this bank. Receives your token and the statement request; returns accounts, balances and transactions.
- GoCardless Bank Account Data (EU/UK), a licensed open banking aggregator — if you connect a European bank (PKO Bank Polski). Receives the connection request; returns account details, balances and transactions. This feature is currently not activated on our server.
- The Ministry of Finance of Poland, HUB paragonowy — if you have connected Polish electronic receipts. Receives your KID; returns your fiscal receipts.
- Checkbox, "Вчасно Каса" and the online office of the State Tax Service of Ukraine — when you scan a Ukrainian fiscal receipt. They receive the receipt identifier from the QR code; they return its contents.
- The National Bank of Ukraine — exchange rates. Receives only a currency code and a date. No personal data. Important: the app fetches rates directly from your device, so the NBU sees your device's IP address, like any website you open.
- Apple and Google — as app stores. Nothing is passed to them from the app's code; they obtain installation data themselves, as independent controllers, under their own policies.
- Apple iCloud — see the next section: on iPhone, a copy of the app's local database is synced to your personal iCloud by default.
We don't hire contractors for marketing, don't pass data to ad networks and don't sell it to anyone.
Transfers of data outside the European Union
The server and the database are located in the European Union (Germany).
Data leaves the EU in three cases:
— a receipt photo goes to Google for recognition (USA and global infrastructure);
— item names may go to Anthropic (USA), if fallback auto-categorisation is enabled;
— if you have connected Monobank, your bank's data is processed in Ukraine.
The legal basis for such transfers: the EU Standard Contractual Clauses (SCC) in our agreements with the recipients and Google LLC's participation in the EU–U.S. Data Privacy Framework; for the transfer to Ukraine — your explicit consent, given by connecting a Ukrainian bank (Article 49(1)(a) GDPR). We state the exact mechanism for each recipient here and update it when a provider changes.
If you don't want your data to leave the EU, don't use photo-based receipt recognition and don't connect the Ukrainian bank — the rest of the app runs entirely on the server in the EU.
How long we keep data
The general rule: as long as you have an account, your data lives. We don't delete it on a schedule, because the point of the app is a history spanning years.
In detail:
— Account (email, name, password hash, settings, profile photo) — until the account is deleted.
— Accounts, transactions, categories, budgets, subscriptions — indefinitely, as long as the space exists, or until you delete them yourself.
— Receipts and their line items, including the stored contents of the QR code — indefinitely; deleted manually or together with the space.
— Item auto-categorisation rules — together with the space or the category.
— Bank connection — until you press "Disconnect bank".
— Connection to the Polish receipts hub — until it is disconnected or until the space is deleted.
— Session records — honestly: they are not deleted. On sign-out and on token refresh we only mark the record as revoked. The rows physically disappear only together with the account. We are fixing this (see the section "What we know about and are fixing").
— Invitations — also not deleted: the invitation row, together with the invitee's address, stays in the database after the invitation has been accepted or has expired. It is deleted only together with the space or with the inviter's account. Also on the list to be fixed.
— Exchange rates — indefinitely; they contain no personal data.
— The cache on the server (membership, the computed plan and the summaries) — from 1 to 5 minutes, exchange rates — 30 days; it expires by itself.
— Server logs — until the container is recreated at the next update; there is currently no time limit. The logs contain no email addresses, passwords, tokens or amounts.
What happens when an account is deleted is described in detail on a separate page, "Account deletion". It also honestly lists what survives deletion.
What is stored on your phone
The app keeps a copy of your data on the device so as to work without internet and open instantly. The copy is the transactions of the last 6 months (up to 10,000 records per space), accounts, categories, budgets, spaces and exchange rates.
On iPhone
— The local database is in the app's sandbox. It is not encrypted with a separate app password; it is protected by the iPhone's own encryption.
— Important: by default this database is synced to your personal iCloud (the private iCloud database, accessible only under your Apple ID). That means a copy of your transactions, balances and notes also sits with Apple, under Apple's rules. We have no access to that copy. If you don't want this — turn off iCloud for Finance in your iPhone's system settings.
— Sign-in tokens are kept in the system keychain (Keychain). They are marked as accessible after the device's first unlock, which means they end up in the encrypted iPhone backup and can be restored onto another phone of yours.
— A profile snapshot (email, name, photo link, appearance settings) is kept in the app's ordinary settings in plain form.
— Honestly: on sign-out the app wipes transactions, budgets, categories, accounts and spaces, but does NOT wipe your email address and the exchange rate cache. This is on the list to be fixed.
On Android
— The local database is an ordinary SQLite file in the app's sandbox, not encrypted with a separate app key; it is protected by device encryption.
— Sign-in tokens are kept in encrypted storage (EncryptedSharedPreferences, with the key in Android's hardware-backed store).
— Backup to Google Drive is disabled for the app — the database and settings don't go to Google's cloud.
— If you have enabled the app lock with a PIN code, what we store is not the PIN itself but a digest of it. Honestly: this digest is not a cryptographic hash, and our PIN protection is weak. It is kept in encrypted storage, but you shouldn't rely on it as a serious barrier. We are reworking this.
— Receipt photos taken with the camera currently stay in the app's temporary cache and are not deleted by our code (they disappear when the app's cache is cleared). We are fixing this too.
— On sign-out, transactions, budgets, accounts, categories and spaces are wiped, but a record with your email address remains. We are fixing this.
Biometrics. The app neither receives nor stores your fingerprint or Face ID: the operating system answers us only "yes" or "no".
How we protect data
What has been done:
— Communication between the app and the server goes over HTTPS with an automatically renewed certificate.
— Passwords are stored only as an irreversible argon2 hash. We can't see them and can't recover them.
— Session refresh tokens are stored only as a hash. The token changes on every use; if someone tries to use an old stolen token, the whole session chain is broken and you are signed out on all devices. Changing the password revokes all sessions.
— Bank secrets and the private access key for the Polish receipts hub are encrypted in the database (AES-256-GCM).
— The database and the cache are not exposed to the internet — they cannot be reached from outside the server.
— The technical API documentation is switched off in the production system.
— Passwords, email addresses, tokens and amounts are not written to the logs. No HTTP request log is kept.
— Every request checks whether you belong to the space whose data you are requesting.
What we do NOT do and will not claim:
— We don't encrypt the database with "end-to-end" encryption. Financial records sit in the database in readable form — otherwise the server couldn't calculate your reports. Only the bank secrets are separately encrypted.
— We cannot guarantee that data passed to the receipt recognition service is processed according to our rules — its rules apply there.
If there is a breach. If a security breach occurs that could harm you, we will notify the supervisory authority within 72 hours, as the GDPR requires, and write to you if the risk to you is high.
What we already know about and are fixing
We decided not to pretend that everything is perfect. Here are the weak spots we found while reviewing our own code, and what is happening with them:
- The profile photo is served over a direct link without sign-in (described above). We are closing that access off behind authorisation.
- The invitation preview page shows the invitee's email address without sign-in. We are removing that address from the response.
- The real-time updates channel currently only checks that you are signed in to Finance, but doesn't check whether you belong to the particular space. We are adding a membership check.
- Notifications about new transactions that a bank can send us are accepted without verifying the sender's signature. We are adding verification.
- Session and invitation records are not deleted over time. We are adding regular cleanup.
- When a bank is disconnected the connection record is deleted, but when an account is deleted it is not; it stays in the database. We are fixing the cascading deletion (details on the "Account deletion" page).
- In the Android version, the "Delete account" button doesn't yet delete data on the server, it only signs you out. Until this is fixed, use deletion by email — how to do that is described on the "Account deletion" page.
- In the iOS version, the network settings allow a connection without encryption if you manually enter a server address without HTTPS. By default the app always works over HTTPS. We are restoring the strict policy.
- The server still accepts unencrypted HTTP requests at the old address — for the sake of previously released builds of the app. We will switch it off once all clients have updated.
- Weak protection of the local PIN code and temporary receipt photo files on Android (described above).
We keep this list up to date: when an item is fixed, it disappears from here.
Your rights
Under the GDPR (and under Ukraine's personal data protection law, if you are in Ukraine) you have the rights to:
- Find out what data of yours we hold, and get a copy of it.
- Correct inaccurate data. You edit your name, email, photo and any records directly in the app.
- Delete data. Account deletion is available in the app and by email — see the separate page.
- Restrict processing while we sort out a disputed matter.
- Take your data in a machine-readable form, in order to move it to another service.
- Object to processing that we carry out in our legitimate interest.
- Withdraw consent — disconnect the bank, disconnect the receipts hub, stop photographing receipts, delete the profile photo, leave a shared space. Withdrawal doesn't undo what was lawfully done before it.
How to exercise them: write to support@serhiip.dev from the address the account is registered to. We answer free of charge and no later than within a month. If the request is complex, we may extend the deadline by a further two months — and we will certainly warn you about that within the first month. If we are not sure the message is from you, we will ask you to confirm your identity — for example, to reply from the account's address or to name details known to the owner.
Where to complain
If you believe we are handling your data wrongly, write to us first — almost everything gets resolved by email. But you are entitled to go to a supervisory authority without doing so:
- Poland: Prezes Urzędu Ochrony Danych Osobowych (UODO), ul. Stawki 2, 00-193 Warszawa, uodo.gov.pl
- Ukraine: Ukrainian Parliament Commissioner for Human Rights (Уповноважений Верховної Ради України з прав людини), ombudsman.gov.ua
- Other EU and EEA countries: the list of authorities is on the website of the European Data Protection Board, edpb.europa.eu
You may go to the authority in your place of residence, at your place of work or at the place of the alleged infringement.
Children
Finance is not intended for children. An account can be created from the age of 16; in Poland and a number of EU countries, giving consent on your own to the processing of data in online services is possible from the age of 16.
We don't verify age at registration — we don't collect a date of birth at all. If you are a parent or guardian and have found out that a child has created an account without your consent, write to support@serhiip.dev: we will delete the account and the data associated with it.
If you run a family budget and want to show a child the expenses — do it from your own account, without creating a separate one for them.
Changes to this policy
If we change the way we work with data, we will update this page and change the effective date at the top.
If a change is significant — for example, a new data recipient or a new purpose of processing appears — we will announce it in the app before the change takes effect.
We keep previous versions and can send them on request to support@serhiip.dev.
This page is available in Ukrainian, Russian, Polish and English — the same languages as the app itself.