Privacy Policy

Privacy & Security White Paper

Every claim below was verified directly against Payd's source code. This document is meant to be checkable, not just readable.

Payd – Paycheck Planner Bundle ID: com.paydplanner.app Document version: 1.6 · Last updated: July 19, 2026 Status: Living document — updated whenever Payd's data handling changes


How to read this document

Every factual claim below was verified directly against Payd's source code or against the current, documented behavior of a named third-party service, on the date this document was last updated. Where a claim depends on a third party's own policies (RevenueCat, Apple, Google), we link to their documentation rather than restate it, because those policies can change on their own schedule.

This document does not use the phrase "bank-level encryption" or similar marketing shorthand. Where we describe encryption, we name the exact algorithm. Where we describe a limitation, we state it plainly rather than omit it.

If anything in this document is ever found to be inaccurate, we will correct it and note the correction in the changelog at the bottom of this page.


1. Executive Summary

Payd is a paycheck-based budgeting app that does not connect to your bank. There is no bank login, no account aggregator (Plaid, Yodlee, Finicity, or similar), and no Payd server that stores your financial data. Every bill, balance, paycheck, and goal you enter is stored locally on your device, using the operating system's standard local storage.

Three narrow categories of network activity exist in the app, described in full in Section 5. Outside of those three, Payd has no way to see, transmit, or store your financial information, because the app has no backend capable of receiving it.

This architecture is a tradeoff, not a marketing claim. It means Payd cannot auto-categorize transactions from your bank the way Copilot or Monarch can, and it means there is no cloud sync between your devices unless you do it yourself via encrypted backup (Section 8) or the optional Partner Sync feature (Section 6). What it buys in return: there is no Payd database to breach, because there is no Payd database.


2. Design Philosophy

Most budgeting apps ask you to link a bank account through an aggregator so the app can pull transactions automatically. That convenience comes with a tradeoff: your login credentials, transaction history, and account balances pass through and are stored by a third party you didn't choose and likely haven't read the terms of.

Payd takes the opposite default. You tell the app what you earn and what you owe. In exchange for a small amount of manual entry — reduced by features like PDF bank-statement import (Section 6), which detects recurring bills from a statement you choose to upload once, without ever transmitting that statement anywhere — your financial picture never has to leave your phone.

This is a deliberate product decision, not a limitation we're working around. It is why the architecture described in this document is possible at all.


3. What Data Exists, and Where It Lives

Everything you enter into Payd is stored using your device's local app storage (AsyncStorage, the standard React Native/Expo local storage layer used by the majority of mobile apps). Nothing here is a Payd server — it is a set of files on your device, inside a storage area the operating system reserves for Payd and does not share with other apps.

Data category Storage key Ever leaves the device?
Pay schedule, bills, balances, spend log, budgets payd_data No
Tax / paystub entries payd_taxes No
Investment portfolio holdings payd_portfolio No
Savings goals & contributions payd_savings No
Theme & appearance settings payd_theme No
Subscription status (Pro/free, trial state) payd_entitlements Anonymized purchase events only — see Section 5
Cashflow chart starting balances payd_starting_balances No
Payday confirmation state payd_payday_confirmation No
Home screen widget data payd_widget_data No
Daily bill-checklist state payd_checklist_* No
Stock-quote provider API keys (optional, user-entered) payd_api_keys Only to that provider, as part of your own quote requests — see Section 6.2
Stock-quote provider API usage counters payd_api_usage No
Cached historical-return calculations (Investment Calculator's opt-in past-performance projection) payd_hist_returns No — this is a local cache of results already fetched under Section 5.1
App Lock on/off preference (optional Face ID / passcode gate) payd_app_lock No — and note this stores only the on/off setting. Biometric data and your device passcode never reach Payd at all; the operating system performs the authentication and returns only a yes/no (Section 7)
App Store review-prompt state payd_review_state No
Last local backup timestamp payd_last_backup_at No

Nothing in this table is transmitted to Payd, because Payd has no server to receive it. There is no account system, no login, and no user ID that identifies you to us — we don't have a "your data" to look up, because we never receive it.


4. What "Local Only" Actually Means, Technically

To be precise about a claim that's easy to overstate: "local only" means Payd's own code never makes a network request containing your financial data. It does not mean your data is invisible to the operating system, to other software running with elevated privileges on a compromised device, or to anyone with unlocked physical access to your phone.

Local storage on iOS and Android benefits from the same OS-level protections as any other app's local data — iOS Data Protection and Android's file-based encryption, both of which are active on a device protected by a passcode, PIN, or biometric lock. Payd does not layer additional encryption on top of this for day-to-day app data, the same way most note-taking or to-do apps don't. If your device itself is compromised (jailbroken, rooted, or unlocked without a passcode), local app storage becomes more exposed — this is true of Payd and true of nearly every app on your phone that isn't using a hardware-backed secure enclave for every field, which comes with real usability tradeoffs most apps (including Payd, today) don't make.

Where we do apply real encryption — your optional local backup file — is described in Section 8, with the exact algorithm named.


5. The Three Things That Touch the Network

Payd makes network requests in exactly three circumstances. Nothing else in the app calls out to the internet.

5.1 Stock price lookups (Portfolio tab, optional)

If you add a stock holding to the Portfolio tab, Payd fetches a current price by sending the ticker symbol (e.g. AAPL) to one of three providers, tried in order: Yahoo Finance's public quote endpoint, then Finnhub, then Alpha Vantage (the latter two only if you've supplied your own free API key for them). This request contains only the ticker symbol — no account information, no identifier tied to you, nothing from any other part of the app. If you never open the Portfolio tab or add a holding, this request never fires.

One related request exists outside the Portfolio tab: when you enter a Finnhub or Alpha Vantage API key in Settings and tap "Test," Payd makes a single validation request to that provider containing a fixed test ticker (AAPL) and the key you just entered — nothing else. This is the same class of request as a quote lookup, fires only when you explicitly test a key, and goes only to the provider the key belongs to.

The Investment Calculator inside the Portfolio tab includes an opt-in checkbox, off by default: "Base on my holdings' past performance." If you tick it, Payd fetches up to 5 years of monthly closing prices for each of your holdings' tickers — from Yahoo Finance's chart endpoint, then Alpha Vantage if you've supplied your own key (Finnhub is not used for this request; its free tier does not offer historical price series) — and computes each holding's annualized return, then weights those returns by position size to fill in the calculator's Annual Return field. This is the same ticker-only request class as the rest of this section: no account information, no identifier tied to you, nothing else from the app. It fires only when you tick the box, never automatically and never in the background, and the results are cached locally for 7 days (payd_hist_returns, Section 3) so reopening the calculator doesn't re-fetch. Unticking the box unlocks the Annual Return field for manual entry and has no further network effect. The calculator always shows the result alongside a disclaimer: "Past performance does not guarantee future results — this is an estimate for planning, not investment advice."

5.2 Subscription purchases (RevenueCat)

Payd uses RevenueCat to process App Store and Google Play subscription purchases and to verify subscription status. This is described in full in Section 6.1.

5.3 In-app rewarded "ads" (currently simulated, not live)

Payd includes an option to earn temporary Pro access by watching a rewarded ad. As of this document's last update, this feature is implemented as a 3-second in-app simulation — no third-party ad network is integrated, and no ad SDK is present in the app's dependencies. To be equally plain about intent: this is a planned feature, not a leftover. The reward flow is already built into the app, and integrating a real ad network is an intended future step — not a hypothetical. If a real ad network is added in a future version, this document will be updated before that version ships, and the specific network, the data it collects, and any consent flow (including Apple's App Tracking Transparency, currently not triggered because no ad SDK is present) will be disclosed here by name.

Everything else — bill entry, balance tracking, the cashflow chart, savings goals, tax estimates, PDF bank-statement parsing, portfolio screenshot import (Section 6.5), the Today screen, notifications, themes — runs entirely offline and makes zero network calls.


6. Third-Party Services, in Full

Payd integrates exactly one paid third-party service (RevenueCat) and three optional data sources (Yahoo Finance, Finnhub, Alpha Vantage). There are no analytics SDKs, no crash-reporting SDKs, and no advertising SDKs currently active in the app. This was verified by inspecting the app's full list of dependencies — there is no Sentry, Firebase, Amplitude, Mixpanel, Segment, or comparable service installed. One planned exception deserves stating here, up front, rather than only in a subsection: ad-supported access is on Payd's roadmap (Section 5.3). No advertising SDK is present today, but when one is added, this document will name the network, describe exactly what data it collects, and document any consent flow — before that version ships, not after.

6.1 RevenueCat (subscription billing)

Payd uses RevenueCat to manage App Store and Google Play subscriptions. Payd does not pass RevenueCat your name, email, or any identifier from within the app. Because Payd never calls RevenueCat's logIn() method or sets a custom user ID, RevenueCat's SDK automatically generates a random, anonymous identifier (documented by RevenueCat as prefixed $RCAnonymousID:) the first time the app configures itself, and that identifier is all RevenueCat associates with your purchase activity.

RevenueCat receives: the anonymous ID, and purchase/subscription lifecycle events (purchased, renewed, canceled, refunded) relayed from Apple or Google. RevenueCat does not receive: your bills, balances, savings goals, or any other data Payd stores — RevenueCat's SDK has no access to that data and Payd never sends it. RevenueCat's own privacy practices are documented at revenuecat.com/privacy.

6.2 Yahoo Finance, Finnhub & Alpha Vantage (stock price lookups)

Described in Section 5.1, including the Investment Calculator's opt-in historical-returns fetch. These receive only a ticker symbol, on-demand — when you view the Portfolio tab, when you test an API key, or when you tick "Base on my holdings' past performance" in the Investment Calculator (Yahoo Finance and Alpha Vantage only for that request; Finnhub does not participate). If you optionally supply your own Finnhub or Alpha Vantage API key (used to raise your personal rate limit for lookups), that key is stored locally on your device and sent only to that provider, as part of your own request to their service.

6.3 Apple / Google push notification infrastructure — not used

Payd's bill and payday reminders are scheduled entirely on-device using each platform's local notification APIs. Payd never requests a remote push token from Apple or Google, and consequently never has one to send anywhere. This means Payd has no mechanism to send you a notification remotely, at all — every notification you receive was scheduled by your own device, in advance, based on data that never left it.

6.4 Partner Sync (optional, user-initiated)

Partner Sync lets two people compare budgets without either party's phone talking to a server — because there is no server. When you tap "Share," Payd generates a snapshot of your data (listed exactly below) and hands it to the operating system's native share sheet. From there, you choose the channel — Messages, AirDrop, email, or anything else installed on your phone. Payd has no visibility into what happens after that; the transmission is entirely between your device and the app you picked.

The snapshot contains: your self-chosen display name, safe-to-spend amount, next payday date, total debt, bill names and amounts (for recurring monthly bills only), and checking/savings totals. It does not contain account numbers, institution names (beyond what you've manually typed as a bill or account label), or transaction-level history.

Important limitation, stated plainly: this snapshot is base64-encoded for compact transport, not encrypted. Anyone who intercepts the encoded string before it reaches your partner could decode and read it. In practice, its confidentiality depends entirely on the security of the channel you choose to send it through — iMessage and most modern messaging apps use their own end-to-end encryption for the message itself, which is what actually protects this data in transit, not anything Payd does to the payload. We recommend sharing it only through a channel you already trust with sensitive information.

6.5 Portfolio screenshot import (optional, on-device)

The Portfolio tab's bulk-add sheet can pre-fill holdings from a screenshot of your brokerage's positions screen, so you don't have to retype each ticker. Precisely what happens, in order:

  1. You pick an image using the operating system's own file/photo picker. This uses the system picker UI, which does not require Payd to hold a photo-library or camera permission — Payd receives only the single image you chose.
  2. The image is copied into Payd's private cache and read by Google ML Kit's on-device text recognition (@react-native-ml-kit/text-recognition, bundled model). Recognition runs entirely on your device; ML Kit's on-device APIs make no network request and the image is never uploaded anywhere.
  3. The recognized text is parsed locally into candidate tickers, share counts, and average costs, shown to you for review and editing. Nothing is saved until you explicitly tap "Add all," and then only the rows you kept — never the image or its raw text.
  4. The cached image copy is deleted the moment recognition finishes — success or failure — in the same code path (finally block in components/BulkAddSheet.tsx, checkable in source). Payd retains no copy, thumbnail, or OCR text.

ML Kit is an on-device library, not a service: it receives no identifier, sends nothing, and is subject to the same "no analytics, no tracking" verification as the rest of the dependency list (Section 6).


7. Permissions Payd Requests

Permission Platform Why
Notifications iOS & Android Local bill and payday reminders, scheduled on-device
Vibrate Android Haptic feedback on notification delivery
Receive boot completed Android Re-schedules local notifications after a device restart (notifications don't survive a reboot otherwise)
Schedule/use exact alarm Android Ensures payday/bill reminders fire at the exact time set, not "roughly around" it
Face ID iOS Optional App Lock (off by default). Authentication is performed entirely by iOS; Payd receives only a success/failure result — never biometric data, never your passcode
Biometric / fingerprint Android Same as above, via Android's BiometricPrompt. These manifest entries are added by the authentication library; Payd stores no PIN of its own — the passcode fallback is your device's own lock screen

Payd explicitly blocks itself from requesting the following, even though some app templates include them by default: contacts (read/write) and call log. There is no feature in Payd that would use them, so the app declares them blocked at the manifest level rather than simply not asking.

Payd does not request: camera access (Partner Sync uses text paste via the share sheet, not a QR scanner), location, microphone, or contacts.


8. Data You Control

8.1 Local backup & restore

You can export a full backup of your Payd data as a file, saved via the OS share sheet — typically to Files/iCloud Drive on iOS or your Android file system, wherever you choose to save it. You control where that file lives; Payd has no involvement once it's saved.

You may optionally protect this backup with a passcode. When you do, Payd encrypts the file using AES-256 in CBC mode, with a key derived from your passcode via PBKDF2 with 10,000 iterations of SHA-256, and a freshly generated random salt and initialization vector on every export. There is no way to recover an encrypted backup if you forget the passcode — Payd never stores it, transmits it, or retains any way to reverse the derivation.

8.2 Full local reset

Settings → Reset All Data permanently erases every category of data listed in Section 3, from every storage location Payd uses on your device — not a subset. This is implemented as a full clear of the app's local storage, not a list of individually-remembered keys, specifically so that no future feature can accidentally be left out of what "reset" means.

One documented exception: RevenueCat's own anonymous identifier (Section 6.1) lives in RevenueCat's native SDK cache, outside the storage area Payd controls, and RevenueCat does not provide a supported way to clear it without a full app deletion. It is not linked to any of your Payd data and carries no information beyond "an anonymous device once configured this app" — but for full precision, a local reset does not remove it. Deleting the app does.

8.3 Deleting the app

After a full reset, Payd offers to help you remove the app itself. What actually happens differs by platform, and we describe both honestly rather than implying parity:


9. How This Compares Structurally to Bank-Linked Budgeting Apps

This is a factual, structural comparison — not a claim that one approach is universally better. Bank-linked apps offer real conveniences Payd does not: automatic transaction import, AI-assisted categorization, and a live view of exactly what cleared your account. Those features require your bank credentials or account data to pass through an aggregator (commonly Plaid, Yodlee, or Finicity) and then be stored by the app's own backend to power search, categorization, and sync across your devices.

Typical bank-linked app Payd
Requires bank login Yes, via an aggregator No
Stores transaction history on a server Yes No server exists
Auto-categorizes spending via AI Often Not currently a feature
Data breach exposes Aggregator + app's own database Nothing — no database exists
Works with no internet connection No (needs to sync/refresh) Yes, entirely
Cross-device sync Automatic, server-mediated Manual (Section 8.1) or Partner Sync (Section 6.4)

If your priority is minimizing how many parties ever see your bank credentials or transaction history, the structural difference above is real and verifiable — not a matter of trusting either company's stated policy, but a difference in what's technically possible to breach.


10. Known Limitations

Stated directly, without hedging:

  1. Local storage is not independently encrypted by Payd. It relies on your device's own lock-screen protection (Section 4). A jailbroken/rooted device, or one unlocked without a passcode, offers reduced protection — this is a real limitation we may address in a future version, and we will update this document when and if we do. The optional App Lock (Section 7) narrows one path to this data — someone holding your unlocked phone can no longer open Payd — but to be precise about what it is: App Lock gates the app's interface. It is not storage encryption, and it does not change what an attacker with filesystem-level access to a compromised device could read.
  2. Partner Sync payloads are not encrypted — only encoded for transport. Their confidentiality depends on the security of the channel you send them through (Section 6.4).
  3. RevenueCat's anonymous identifier persists after a local data reset, until the app itself is deleted (Section 8.2).
  4. True self-deletion is impossible on iOS by Apple's own design — Payd cannot remove itself from your device without your final manual tap (Section 8.3).
  5. The "watch an ad" Pro-access feature is currently simulated, not backed by a live ad network (Section 5.3) — and it is a planned feature, not a discarded experiment. When a real ad network is integrated, it will collect data the rest of the app does not; the network and its data practices will be named here before any ad-enabled version ships.

11. Security Practices We Follow

Payd has no backend server, no database, and no API endpoints of its own — which means the majority of a standard web-app security checklist (row-level database security, server-side input validation, rate limiting, CORS configuration, SQL injection prevention) does not apply, because there is no server-side surface for those risks to exist on. This isn't a loophole; it's the direct consequence of the architecture described in Section 1.

What we do apply, given that architecture:


12. Changelog

v1.6 — July 19, 2026 New feature disclosed before ship, per the living-document policy:

  1. App Lock added (Sections 3, 7, 10, 11). An optional, off-by-default toggle in Settings → Privacy requires Face ID, fingerprint, or the device passcode to open Payd. Authentication is delegated entirely to the operating system — Payd receives only a success/failure result, never biometric data or the passcode, and stores no PIN of its own. The single new stored value is the on/off preference (payd_app_lock), cleared by Reset All Data like everything else. New OS permission entries: Face ID usage description (iOS) and biometric/fingerprint manifest entries (Android). If the device has no lock screen at all, App Lock fails open rather than locking you out of your own data, and cannot be enabled until one is set. Known Limitation #1 updated to state precisely what App Lock is (an interface gate) and is not (storage encryption). Not available on web builds.

v1.5 — July 19, 2026 New feature disclosed before this document's first publication:

  1. Investment Calculator's opt-in historical-returns projection added (Sections 3, 5.1, 6.2). An off-by-default checkbox — "Base on my holdings' past performance" — lets the calculator's Annual Return field be computed from your actual holdings' history instead of a manual guess. Ticking it fetches up to 5 years of monthly closing prices per ticker (Yahoo Finance, then Alpha Vantage if you've supplied a key), computes each holding's annualized return, and weights the result by position size. Same ticker-only request class as the existing price lookup in Section 5.1 — fires only when the box is ticked, never automatically, and results cache locally for 7 days (payd_hist_returns, added to Section 3's storage table). The calculator always displays the disclaimer: "Past performance does not guarantee future results — this is an estimate for planning, not investment advice."

v1.4 — July 19, 2026 Transparency correction, prompted by our own review — no code or data handling changed:

  1. Rewarded-ad intent disclosed up front. Previous versions described the rewarded-ad feature as "currently simulated" but left the planned nature of real ad integration easy to miss. Sections 5.3, 6, and 10 now state plainly that ad support is a planned feature with its reward flow already scaffolded in the app, and repeat the commitment that any ad network will be named here — with its data collection and consent flow — before an ad-enabled version ships. Marketing copy on this site was softened to match ("no analytics or tracking SDKs" rather than implying ads were never coming).

v1.3 — July 13, 2026 New feature disclosed before ship, per the living-document policy:

  1. Portfolio screenshot import added (Section 6.5). Holdings can be pre-filled from a brokerage screenshot using Google ML Kit's bundled, on-device text recognition. No network request is involved, the image is picked via the OS's own picker (no photo-library permission), and the cached copy is deleted immediately when recognition ends — the deletion lives in the same finally block as the recognition call, so no code path can skip it. A bulk manual-entry sheet (ticker, shares, average price) ships alongside it; both are Pro features inside the Portfolio tab.

v1.2 — July 8, 2026 Four additions/corrections, prompted by a full source re-audit (PRIVACY_AUDIT.md v2.0.0):

  1. API-key validation request disclosed. Testing a Finnhub or Alpha Vantage key in Settings makes one validation request to that provider, containing a fixed test ticker (AAPL) and the user's own key. Same data class as a quote lookup; previously undocumented. Section 5.1 updated.
  2. payd_api_keys added to the storage table (Section 3). User-entered provider API keys were already described as stored locally in Section 6.2, but the table omitted the row.
  3. Final Rork remnant removed. A leftover, inert build-config entry from the removed development platform (an expo-router origin pointing at the platform's domain) remained in app.json after the v1.1 cleanup. No request was ever made to it — the app contains no relative network calls that would use it — but it has now been deleted so the v1.1 "removed entirely" claim holds by construction. For clarity: identifiers such as payd_bill_*, payd_longterm_*, and payd_payday_check that appear in the app's source are names of locally scheduled notifications, not stored data, and so do not appear in Section 3's storage table.
  4. Eight unused packages removed from the dependency list. zod, zustand, expo-symbols, expo-image, expo-web-browser, expo-font, @expo/vector-icons, and react-native-worklets had zero references in Payd's source and were uninstalled. None had any network behavior, so nothing about the app's data handling changes — this simply shrinks the dependency surface that Section 6's "verified against the app's full list of dependencies" claim covers.

v1.1 — July 8, 2026 Two corrections, noted here per the policy at the top of this document:

  1. Alpha Vantage disclosed as a third stock-quote provider. The quote fallback chain has three providers (Yahoo Finance → Finnhub → Alpha Vantage), not two. Like the others, Alpha Vantage receives only a ticker symbol, and only when you've supplied your own free API key. Sections 5.1 and 6.2 updated.
  2. Development-platform analytics tooling removed from the build. The app was originally scaffolded on a development platform (Rork) whose build tooling automatically injected an analytics wrapper — backed by the PostHog SDK, pointed at the platform's own relay — into every build. It was dormant in Payd (the environment variables that activate it were never set, and no data was ever transmitted), but its presence in the compiled app contradicted this document's claim that no analytics SDK is bundled. That build tooling and the SDK it carried have now been removed entirely, along with unused server-framework and permission-bearing packages (expo-location, expo-image-picker) left over from the same template, so the claim is true by construction rather than by configuration.

v1.0 — July 8, 2026 Initial publication. Documents the local-first architecture, the three network-touching features (stock lookups, RevenueCat, simulated ad rewards), Partner Sync's unencrypted-transport limitation, AES-256 backup encryption, full-reset behavior, and platform-specific app deletion.


Questions or corrections

If you find anything in this document that doesn't match Payd's actual behavior, we want to know — please reach out so we can correct it. This document is meant to be checkable, not just readable.