Privacy Policy
This Privacy Policy explains how PennyPulse ("we", "us", "the service") processes personal data when you use the website at pennypulse.io and the application at app.pennypulse.io. We process data under the EU General Data Protection Regulation (GDPR) and the German Federal Data Protection Act (BDSG).
1. Controller
The controller responsible for personal data processing under Art. 4(7) GDPR is:
Frederik Martin
Alfred-Kästner-Str. 59
04275 Leipzig
Germany
Email: hello@pennypulse.io
PennyPulse is operated as a sole proprietorship. There is no statutory obligation to appoint a Data Protection Officer (DPO) at this stage; for any questions about your data, please contact us at the email above.
2. What data we process
2.1 Account data
When you register, we store:
- Email address
- A bcrypt hash of your password (never the password itself)
- Account creation and last-update timestamps
- Email-verification status
- Your subscription tier
2.2 Financial data you enter
PennyPulse is a budgeting tool, so by design we store the income, expense, account-balance, project, category, and KPI data you choose to enter. This data is stored in our database in Germany and is accessible only via your authenticated session.
The sensitive fields you enter — transaction amounts, fees and descriptions, account names and descriptions, project names, and the names and descriptions of any custom KPIs you create — are encrypted at rest with a key derived from your password (see Section 8). Other fields used for filtering and aggregation (dates, transaction types, currencies, exchange rates, and the identifiers of accounts, categories, and projects) are stored in plain form so the application can sort, group, and query them.
2.3 Authentication and session data
We issue short-lived access tokens (JWT) and longer-lived refresh tokens to keep you signed in. For each active session we record a hash of the refresh token, the device identifier you supply, your IP address, your browser's User-Agent string, and the last time the session was used. You can review and revoke individual sessions in your account settings.
2.4 Activity log
We keep an internal audit log of security-sensitive actions you take — login, logout, password change, session revoke, account creation. Each entry includes a timestamp, the action, your IP address, and your User-Agent. This log helps us detect and investigate unauthorised access.
2.5 Billing data (when you subscribe to a paid plan)
Payment processing is handled by Stripe (see Section 4). We store your Stripe customer ID, your subscription tier, current-period end date, and trial status. We do not store your full card number, CVC, or other sensitive payment details — those live with Stripe.
2.6 Server logs
Our application server records standard HTTP request logs (method, path, status, IP, User-Agent, timing). These logs help us debug errors and investigate abuse. Hetzner, our hosting provider, additionally maintains short-term network-level logs under their own retention policies.
3. Why we process this data and on what legal basis
- To provide the service (Art. 6(1)(b) GDPR — performance of a contract). We need your account data, the financial data you enter, and your active sessions to render the application you're paying for.
- To send transactional emails — email verification and billing receipts (Art. 6(1)(b) GDPR). These emails are necessary to operate your account.
- To process payments (Art. 6(1)(b) GDPR for subscribers, and Art. 6(1)(c) for invoice retention obligations under German tax law).
- To keep the service secure — activity log, session tracking, rate limiting (Art. 6(1)(f) GDPR — legitimate interest in protecting our users and the service).
4. Sub-processors and recipients
We share data with the following carefully selected processors:
| Processor | Purpose | Location |
|---|---|---|
| Hetzner Online GmbH | Server hosting and database | Germany |
| Stripe Payments Europe Ltd. | Subscription payments | Ireland (EU) |
| Resend, Inc. | Transactional email | United States (with EU sub-processors and SCCs in place) |
| Namecheap, Inc. | Domain registration and authoritative DNS | United States |
| Lumin (Tamso Labs) | Error tracking on the marketing site and the application at app.pennypulse.io (always on, legitimate interest in service stability); product analytics on the same sites (only after you consent) | Germany |
For transfers to processors outside the EU (Resend, Namecheap), we rely on the EU Commission's Standard Contractual Clauses (SCCs) and, where applicable, the EU–U.S. Data Privacy Framework. Each processor has its own privacy policy describing its handling of data:
- Hetzner Privacy Policy
- Stripe Privacy Policy
- Resend Privacy Policy
- Namecheap Privacy Policy
- Lumin Privacy Policy
We do not sell your data, share it with advertising networks, or use it for profiling or automated decision-making with legal effect.
5. Cookies and similar technologies
The application at app.pennypulse.io uses a server-set, HttpOnly,
SameSite session cookie (strictly necessary under Art. 6(1)(b) GDPR —
no consent required), and a long-lived deviceId stored in
localStorage on your browser to identify your device for
session management.
On the marketing site and inside the application at app.pennypulse.io we use a third-party tool (Lumin, see Section 4) for two distinct purposes:
Error tracking (always on, Art. 6(1)(f) GDPR — legitimate interest). When an unhandled error occurs in the page, Lumin receives the error message, stack trace, page URL, and a randomly generated session identifier. We rely on this telemetry to detect and fix bugs and to keep the service stable and secure, which we consider a legitimate interest that is not overridden by your interests. The payload contains no email address, no name, and none of the financial data you enter. You can object to this processing under Art. 21 GDPR by writing to hello@pennypulse.io.
Product analytics (consent-based, Art. 6(1)(a) GDPR). We use Lumin to understand which pages are visited and which actions — such as signing in, creating a transaction, or upgrading a subscription — succeed or fail. These events are sent only after you give your consent via the consent banner shown on first visit to either site; if you decline or have not yet chosen, no analytics events are sent. You can revoke consent at any time using the "Cookie settings" link in the marketing-site footer or the Privacy screen inside the application. Analytics events contain the same randomly generated session identifier, the page URL, and the event name; they do not contain your email address or the financial data you enter.
We do not use advertising or cross-site tracking, and we do not share any data from either purpose with third parties for advertising.
6. How long we keep your data
- Account and transaction data: kept for as long as your account is active. When you delete your account, we delete your data within 30 days.
- Billing records: kept for up to 10 years after the end of the relevant fiscal year, as required by German commercial and tax law (§ 257 HGB, § 147 AO), even after account deletion.
- Activity log entries: kept for 12 months, then automatically deleted.
- Server request logs: kept for 30 days, then rotated out.
- Pending tokens (email verification, password reset): kept until used or expired (typically 1 hour), then cleared on the next use.
7. Your rights under GDPR
You have the right to:
- Access the personal data we hold about you (Art. 15).
- Rectify inaccurate data (Art. 16).
- Erase your data, subject to legal retention requirements (Art. 17).
- Restrict processing in certain circumstances (Art. 18).
- Receive a copy of your data in a portable format (Art. 20). You can export all your transactions as CSV from within the application at any time.
- Object to processing based on legitimate interest (Art. 21).
- Withdraw consent you have previously given (e.g. for product analytics), without affecting the lawfulness of past processing (Art. 7(3)).
- Lodge a complaint with the supervisory authority responsible for your place of residence or work (Art. 77). The supervisory authority for our establishment is the data protection authority of the federal state in which our registered address is located.
To exercise any of these rights, email hello@pennypulse.io. We will respond within one month (Art. 12(3) GDPR), or sooner where possible.
8. Security
We protect your data with measures appropriate to its sensitivity:
- TLS (HTTPS) for all transport between your browser and our servers.
- Passwords stored as bcrypt hashes; email-verification and session tokens stored as SHA-256 hashes.
- Short-lived JWT access tokens, with refresh tokens revocable per session.
- All sessions other than the current one are revoked when you change your password. When you recover your account using a recovery code, all sessions are revoked and you must sign in again with your new password.
- Rate limiting on authentication endpoints to slow brute-force attempts.
- Database hosted on Hetzner servers in Germany, with daily backups.
- Per-user encryption at rest of sensitive financial data — including transaction amounts, fees, descriptions, account names, project names, and custom KPI fields (see Section 8.1).
8.1 Per-user encryption at rest
The sensitive fields you enter are encrypted in our database with a key that is unique to your account and derived from your password. Each user has a distinct data-encryption key (DEK), so a compromise affecting one user does not expose other users' data. The encrypted fields include: transaction amounts, fees, and descriptions (including for recurring transactions); account names and descriptions; project names; and the names and descriptions of any custom KPIs you create.
Some fields are deliberately left unencrypted so the application can filter and aggregate on them: dates, transaction types, currencies, exchange rates, and the identifiers of accounts, categories, and projects. Built-in categories (e.g. "Groceries", "Rent") are also unencrypted because they are shared global data, not per-user content.
Your DEK is held in our server's memory only for the duration of an active session and is dropped when you log out or when your session expires. It is never written to disk in unencrypted form. Encrypted database backups contain ciphertext only and cannot be read without your password.
Recovery code: when you first log in, we generate a single-use recovery code derived from a separate random key and show it to you exactly once. You can save it to a password manager. If you forget your password, you can use this recovery code together with a new password to regain access to your data; the recovery code is rotated when used, so any previously-shown code stops working. You can also generate a new recovery code at any time from Settings → Security.
Important consequence: if you lose both your password and your recovery code, your encrypted data is unrecoverable — we cannot decrypt it without keys we don't have. Please use a memorable password and store your recovery code somewhere safe.
9. Changes to this policy
We may update this policy from time to time — for example when we add new sub-processors, change retention periods, or introduce new features. We will update the "Last updated" date at the top of this page and, for material changes affecting your rights, we will notify you by email or via an in-app message before the changes take effect.
10. Contact
Questions, requests, or concerns about this policy or your data: hello@pennypulse.io.