The user's transactions, budgets, and credit-card schedules in Pennyworth live in local storage on the phone — the structured channels out are the in-app CSV export and the kakeiboData.zip backup that the app writes to Google Drive on Android or iCloud on iOS. The device is the system of record, and data moves only when the user runs an export or a restore. That single shape is what an integration has to honour, and it is also what makes the integration straightforward once you have an authorized sample export to design against.
For most jobs we recommend doing both: parse the CSV for routine transaction-level ingest (it is human-readable, easy for the user to produce, easy to refresh) and reach into the backup ZIP only when the consumer needs the structures the CSV flattens out — recurring items, instalment schedules, asset-and-transfer linkage. The two together cover roughly the full shape the app holds.
What sits inside the ledger
| Domain | Where it originates in the app | Granularity | Useful for |
|---|---|---|---|
| Transactions | Income, expense, and transfer entries logged through the quick-add screen or imported from receipts | Per entry: date, amount, currency, account, category, tags, memo, photo reference | Personal finance dashboards, tax aggregation, expense reimbursement systems |
| Books | The "one app, multiple accounting books" feature — personal / family / company kept separate | Per book: name, currency default, member list (where shared) | Bookkeeping handover, separating household and side-business reporting |
| Accounts and assets | Cash, bank savings, credit cards, loans, investment lines under unified asset management | Per account: opening balance, current balance, type, currency | Net-worth views, asset-side reporting, balance reconciliation |
| Transfers | Movement between accounts — ATM withdrawals, credit-card payments, e-money top-ups | Paired debit/credit lines linked to a transfer event | Avoiding double-counting on import; reconstructing cash-flow timing |
| Categories and smart tags | User-defined hierarchy plus cross-category tags ("Travel", "Business Expenses") | Tree of categories; flat set of tags per transaction | Slice-and-dice reporting, cross-cutting filters that categories alone do not cover |
| Budgets | Plan-vs-actual envelopes set per category and period | Per envelope: scope, period, target, current consumption | Budget compliance, envelope-style downstream tools |
| Recurring items | Auto-fill rules for salary, rent, subscriptions | Schedule template with cadence, amount, account, category | Forecasting cash flow, mirroring scheduled items into another tool |
| Credit-card schedules | Repayment dates, due amounts, instalment plans | Per card: cycle, statement balance, instalment chain | Debt-paydown apps, statement reconciliation |
| Foreign currency balances | Native-currency holding across 130+ currencies with daily FX | Per account: native amount; per FX day: rate used | Multi-currency net-worth, expat budgeting, FX-aware reporting |
| Receipt photos and invoices | Attached images for transactions and the invoice receipt feature | Per attachment: image bytes plus the transaction link | Expense audit, reimbursement evidence, archival |
Routes to the data, ranked
1. CSV export — the everyday channel
The user runs the in-app export and we get a UTF-8 CSV with one row per transaction plus header rows for accounts. This is the route to design for first: it is what end users can produce themselves, it refreshes on demand, and it is the channel the app's own FAQ treats as primary (the FAQ even troubleshoots export failures involving the device's Mail app). Cost to set up is low; durability is high because the app has shipped this export for years.
2. kakeiboData.zip backup — for the structures CSV loses
The cloud-backup container that lands in Google Drive or iCloud — referenced by name in Swallow Works Studio's own FAQ when troubleshooting a failed restore. The ZIP holds richer internal structures than the CSV: recurring-item templates, instalment chains, full transfer linkage, multi-book separation, and attachment manifests. Layout is not officially documented; we map it once against an authorized sample and pin the parser to the producing version. We arrange access to a sample export with the customer during onboarding.
3. Local database extraction — only when warranted
For forensic, migration, or full-history use cases where neither CSV nor the backup ZIP carries enough, we read directly from the on-device store with the user's consent. This is heavier and slower, and we only propose it when the downstream consumer genuinely needs it (e.g. you are moving someone off Pennyworth entirely and want every soft-deleted record).
For a typical engagement we ship route 1 as the primary ingest path and route 2 as the secondary channel for the fields the CSV does not carry. Route 3 stays as an option, not a default.
A parser sketch
Illustrative only — the field names below are what we typically see in current exports and confirm against the customer's actual file during the build, since the app has revised the export across versions.
import csv, zipfile, json
from datetime import datetime
from pathlib import Path
def read_pennyworth_csv(path: Path):
"""Iterate transaction rows from a user-produced CSV export.
Header columns confirmed during onboarding against the customer's file."""
with open(path, encoding='utf-8-sig', newline='') as fh:
reader = csv.DictReader(fh)
for row in reader:
yield {
'date': datetime.strptime(row['Date'], '%Y/%m/%d').date(),
'book': row.get('Book') or 'default',
'account': row['Account'],
'category': row['Category'],
'tags': [t for t in (row.get('Tag') or '').split(',') if t],
'amount': float(row['Amount']),
'currency': row.get('Currency', 'JPY'),
'memo': row.get('Memo') or None,
'is_transfer': row.get('Type', '').lower() == 'transfer',
}
def open_backup(zip_path: Path):
"""Walk the kakeiboData.zip backup container Pennyworth writes to
Google Drive (Android) or iCloud (iOS). Internal layout is mapped
during the build against an authorized sample backup."""
with zipfile.ZipFile(zip_path) as zf:
manifest = json.loads(zf.read('manifest.json')) # name confirmed per version
for entry in manifest['books']:
yield {
'book': entry['name'],
'currency': entry.get('default_currency'),
'accounts': entry['accounts'], # opening balance, type, currency
'recurring': entry.get('recurring', []),
'instalments': entry.get('instalments', []),
}
def reconcile_transfers(rows):
"""Pair the two legs of a transfer so a payday + ATM withdrawal
does not get counted twice on the way into a downstream ledger."""
legs = {}
for r in rows:
if not r['is_transfer']:
yield r; continue
key = (r['date'], abs(r['amount']))
if key in legs:
a, b = legs.pop(key), r
yield {'kind': 'transfer', 'date': a['date'],
'from': a['account'] if a['amount'] < 0 else b['account'],
'to': b['account'] if a['amount'] < 0 else a['account'],
'amount': abs(a['amount']), 'currency': a['currency']}
else:
legs[key] = r
What you receive
Output of a standard Pennyworth engagement is a small, focused package — not a generic SDK. It is shaped around the two real channels (CSV and backup ZIP) and the data domains your downstream system actually needs:
- Runnable parser source in Python or Node.js for the CSV export and the kakeiboData.zip container, with the transfer-pairing logic so balances do not double-count.
- An OpenAPI specification describing the normalized JSON your system will consume — transactions, accounts, books, recurring rules, instalments — so other services can be wired against a stable contract rather than the raw export shape.
- A short auth-and-handoff note: how the user is walked through producing the export, what they touch, what they upload, and where the data lives in your pipeline.
- Automated tests against an anonymized sample backup we agree on at the start, including the awkward cases (multi-book consolidation, foreign-currency transfers, soft-deleted entries that linger in the ZIP).
- Interface documentation aimed at the engineer who will own this in six months — field meanings, version drift to watch for, the bits we deliberately left out and why.
Engineering notes we work through during the build
These are the parts that bite if you treat Pennyworth as a flat transactions file and ship the first parser that runs. We handle them as part of the build rather than handing them to you as caveats:
- The CSV column set has shifted across Pennyworth versions — the app has been on the stores for years and the export today is not byte-identical to older exports. We pin the parser to the version that produced the customer's file and keep a small adapter layer so a future export with a new column does not silently drop data.
- kakeiboData.zip is not officially documented; the layout we model is what we confirm against an authorized sample backup. We arrange a clean sample with the customer at the start of the engagement, so the parser is mapped to a real producing version rather than guessed at.
- Categories and tags can come back in mixed scripts depending on the user's locale — the app has Japanese roots ("rakuraku kakeibo" → "easy household ledger") and is used across English, Japanese, and Chinese. We normalize the label set during ingest so downstream lookups do not silently miss a category written in a different script.
- Asset balances depend on transfers being paired, not double-counted. We wire the transfer reconciliation into ingest itself, so an ATM withdrawal plus a salary deposit do not show as four independent events to whatever sits downstream.
- Multi-currency totals require an explicit FX policy. Pennyworth applies its own daily rate inside the app; if the consuming system wants stable historicals, we re-resolve FX against a feed you choose and store both the native and the home-currency amount.
Privacy footing for an export-driven ledger
Because nothing leaves the device until the user runs an export, the dependable legal basis is the user's own consent — they own the file and choose to hand it to your system. The applicable privacy regime is wherever the user sits: GDPR for EU users, APPI in Japan (relevant given the app's lineage), CCPA in California, plus equivalents elsewhere. The studio's posture is data-minimization on receipt: we parse only the fields the downstream actually needs, redact the rest before they hit logs, and define a retention window with you up front. Where a deployment touches employee data (corporate book usage), we sign an NDA and document the lawful basis before any sample backup changes hands.
Pricing
For Pennyworth specifically the smallest engagement we run delivers a CSV parser, the kakeiboData.zip reader, the normalized OpenAPI spec around them, and a test suite against an anonymized sample — that package starts at $300 and is billed only after you accept the build. If you would rather not host the parsers yourself, we expose the same pipeline as a hosted endpoint and charge per call, with no upfront commitment. Delivery is one to two weeks from a confirmed sample export. Tell us the slice of the ledger you actually need at /contact.html and we will scope from there.
Provenance
Sources opened during this mapping: the Play Store listing for the Android build, the App Store listing for the iOS build, and the developer's own FAQ — including the specific backup-error page that names the kakeiboData.zip container. Checked in May 2026.
- Pennyworth on Google Play (com.swalloworkstudio.rakurakukakeibo)
- Pennyworth Expense Tracker on the App Store (id 954944283)
- Swallow Works Studio — Pennyworth FAQ index
- Pennyworth FAQ — kakeiboData.zip backup-error guidance
Mapping reviewed by the OpenBanking Studio integration desk, May 2026.
Adjacent ledgers in the same shape
Pennyworth sits in a crowded category of personal-finance ledgers — most of them face the same export-driven integration question, with the details varying by how much they cloud-sync. The names below are neutral references for an integrator scoping a unified pipeline across several apps; we are not ranking them.
- Money Lover — multi-account budget ledger with CSV export and a cloud-sync tier; similar transfer model to Pennyworth.
- Wallet by BudgetBakers — connected accounts plus manual entries, with structured exports an integrator can target.
- Spendee — wallet-and-budget ledger with shared spaces and CSV out.
- Goodbudget — envelope budgeting with a household-sharing model; exports the envelope state, not just transactions.
- 1Money — lightweight expense tracker focused on quick entry and on-device storage.
- Monefy — minimalist offline expense tracker with CSV backup; closest in shape to Pennyworth's local-first stance.
- Money Manager (RealByte) — double-entry-style ledger with asset accounts and exports.
- AndroMoney — long-running budget tracker with multi-currency and CSV export, common in East-Asian app stores alongside Pennyworth.
Questions integrators actually ask about Pennyworth
What's actually inside the kakeiboData.zip backup, and is it documented?
The backup container is an internal layout the app writes when you back up to Google Drive (Android) or iCloud (iOS). It is not formally documented by Swallow Works Studio; we map it during the build by unpacking an authorized sample export, and the parser we ship is keyed to the version that produced your data.
Does the CSV export carry credit-card installment schedules and recurring items?
The CSV carries posted transactions, including instalment lines once they post, but it does not consistently expose the underlying repayment schedule or the recurring-item template. Where the schedule matters (forecasting, debt-paydown apps), we read those structures from the backup ZIP, which retains the recurring and instalment metadata the CSV flattens out.
How do you consolidate Pennyworth's separate personal, family, and company books?
Books are first-class in the backup and tagged in the CSV's Book column. We treat each book as its own ledger during ingest, then optionally merge them on a shared chart of accounts you supply. Merging is opt-in because a household and a small-business book usually want distinct tax and reporting paths.
Can multi-currency balances be reconstructed correctly from an export?
Yes, but you have to pin the FX policy. Pennyworth holds amounts in their native currency and applies its own daily rate for in-app totals. For an integration we usually re-resolve historical FX at the transaction date against an external feed and store the home-currency value alongside the native one, so downstream reports do not drift when rates update.
Interface evidence
Screens from the public store listing — useful when scoping which surfaces the customer actually wants ingested. Click to enlarge.
App profile (factual recap)
Pennyworth - Spending Tracker is published by Swallow Works Studio (developer contact swalloworks@gmail.com, per the store listing) and shipped for both Android (package com.swalloworkstudio.rakurakukakeibo) and iOS (App Store id 954944283). The app describes itself as a local-first personal finance ledger covering transactions, budgets, accounts, credit cards, recurring items, multi-currency balances across 130+ currencies, smart-tag categorization, and multiple books (personal, family, business) inside one app. Storage is on-device first, with Google Drive (Android) or iCloud (iOS) for backup and a CSV export channel for direct file handoff. Privacy is locked behind a pattern, Touch ID, or Face ID. The app's heritage is Japanese household-budgeting (kakeibo) — visible in the package name and in the FAQ — and it ships in English, Japanese, and Chinese.
Updated 2026-05-30.