Use JSON when you need transaction data in a script or data pipeline while retaining the statement's account metadata. Our JSON download is one object containing metadata and a transactions array. It is not a bare list of rows or a line-delimited JSON file.
Download the structured statement
- Open the PDF to JSON tool and upload a readable, unlocked PDF of up to 25 MB.
- Select Convert My Statement and wait for processing.
- Open More formats, then select JSON under Spreadsheet+.
- Save the file and compare a sample of its dates and amounts with the original PDF.
This guide covers reading a downloaded file. A JSON export does not itself establish a public API integration or an automated upload workflow.
Understand the object structure
| Field | Shape | Meaning |
|---|---|---|
| bankName, accountHolder, accountNumber | String or null | Extracted account metadata |
| currency | String or null | Statement-level currency |
| statementPeriod | Object with from and to | Date strings or null for each boundary |
| openingBalance, closingBalance | Number or null | Extracted statement balances |
| transactions | Array | Rows containing date, description, debit, credit, balance |
| pageCount | Number | PDF page count recorded during conversion |
| validated | Boolean | Result of the application's balance check |
| parserUsed | String | Extraction provider identifier |
Within each transaction, date and description are strings; debit, credit, and balance are numbers or null. The parser is asked for ISO dates, but your integration should still validate them. Account numbers are identifiers: keep them as strings so leading zeros are preserved. There is no category or original bank transaction ID field in this export.
Read the transaction array in Python
Save your download as statement.json for this example. Python's json module reads the outer object; select its transactions field to get the rows. Using Decimal for fractional numbers avoids adding binary floating-point rounding during your own calculations. See the Python JSON documentation for json.load and parse_float.
python
import json
from decimal import Decimal
with open("statement.json", encoding="utf-8") as source:
statement = json.load(source, parse_float=Decimal)
rows = statement["transactions"]
if not isinstance(rows, list):
raise ValueError("Expected a transactions array")
print("Balance check:", statement["validated"])
for row in rows:
print(row["date"], row["description"], row["debit"], row["credit"])The example reads and displays data; it does not post transactions anywhere. If you later use a dataframe, build it from the transaction array and store statement metadata separately. Reading the whole object as though it were a flat transaction table mixes fields with different shapes.
Interpret null and validated carefully
Null means a value was absent or unavailable. It is not interchangeable with zero. A missing debit is normal for a credit row, but a missing opening balance needs a different decision. Check these cases explicitly before totals or imports.
The validated flag checks that there are transactions and both statement balances, then compares opening balance plus credits minus debits with closing balance within a tolerance of 0.01. It does not verify every description, date, account identifier, or running balance. A false value can mean missing balances or a mismatch; a true value is not proof that every row is correct.
Prepare data for a repeatable workflow
Check expected keys and types, date validity, statement currency, and the account before loading rows. Keep a source-file reference with imported records. The export has no persistent bank-issued row IDs, so design your own duplicate review instead of assuming row order is unique across files.
For categories, download the separate categorised workbook. For a simpler flat file, follow the CSV guide.