# Changelog of Bank Statement Converter: PDF to CSV, Excel, QuickBooks & Xero (`humble-echidna/bank-statement-converter`) Actor

- **URL**: https://apify.com/humble-echidna/bank-statement-converter/changelog.md
- **Full Actor documentation**: https://apify.com/humble-echidna/bank-statement-converter.md

## Changelog

Versions follow MAJOR.MINOR.PATCH (`src/version.ts`); Apify shows MAJOR.MINOR from `.actor/actor.json`.
Every run logs its version and the engine commit, and records both in the `RUN_STATS` key-value record.

### 0.1.3 (2026-11-04)

- Xero CSV: a bank CSV's check number that starts like a formula now gets an apostrophe, like the other text columns.
- Engine updated to the current Cleanrow engine, which also brings its CSV fixes: more currency codes and symbols read in
  amounts, and a note on debit or credit columns that mix signs. No change to price.

### 0.1.2 (2026-10-16)

- A run that returns nothing (every input bad, private, blocked or unreachable, or an empty input) now ends
  SUCCEEDED with an empty dataset and the reason as its status message and in the log, instead of FAILED. Only an
  unexpected error still fails the run. `RUN_STATS` keeps the reason as before.
- No change to output fields or price.

### 0.1.1 (2026-10-14)

- Engine re-vendored at 2d19e31: the account-number pattern no longer backtracks exponentially on a line of many
  asterisks (such a PDF used to run into the 120 s parse limit and fail, uncharged; now it's read normally).

### 0.1.0 (2026-10-14)

First release. A Node actor (the rest of the portfolio is Python): the conversion is the Cleanrow engine,
vendored unchanged from `mms/statements/engine/src` at 635a9b9 (`src/engine/MANIFEST.json`).

- Statement PDFs (with a text layer) and bank CSV exports from links in; one summary row per statement (the balance
  check: opening + transactions = closing, verified/mismatch/unavailable, the difference, the rows where it breaks),
  then one row per transaction (date, description, amount in cents and as a decimal, running balance, currency).
- PDFs with several accounts give one statement per account. CSV: signed, debit/credit and type-column exports,
  any delimiter, comma decimals, UTF-16/Windows-1252; ambiguous dates refused until Date order is set.
- Optional QuickBooks Online CSV, Xero CSV and OFX files per statement in the key-value store, from the engine's
  exporters.
- Charged per statement through a `statement-converted` event, only for statements with transactions, every row
  imported and a balance check that didn't fail. Max statements per run, and the maximum cost per run honoured: a
  statement is delivered only if it can be paid for, and links past the limit aren't downloaded.
- Each file is parsed in a worker thread with a 120 s limit and a heap cap, so a PDF that sends the engine's
  account-number pattern into exponential backtracking fails only itself (README "Engine notes"); PDFs over Max pages
  per statement (100, at most 200) are refused before parsing.
- Downloads follow the repo's fetch rules (ACTOR-CHECKLIST.md 2b), in TypeScript since mms_common is Python: honest
  User-Agent, robots.txt per origin, public addresses on ports 80/443 only on every redirect hop, the connection pinned
  to the checked address, a 30 MB cap and a 120 s deadline per file.
- Sources and terms: the actor reads only files the user links to; no site is scraped and no login is used, so no
  third-party API or terms apply beyond the hosting site's robots.txt, which is followed. The default input is a
  synthetic sample statement on our own site (whitehatharbor.com/statements/sample-statement.pdf; robots.txt allows
  all, read 2026-10-13).
