Bank Statement API for Developers: Complete Integration Guide 2026
TL;DR
A bank statement API takes a PDF upload and returns structured JSON — a transactions array with date, description, amount, and balance, plus page count and detected format. Authenticate with an API key, POST the file to the extract endpoint, and handle the synchronous response or a webhook for large files. Most APIs bill per page.
Bank Statement API: Complete Integration Guide for Developers
Whether you're building a fintech app, accounting software, or a data pipeline, integrating bank statement parsing via API saves months of development time.
Why Use an API Instead of Building Your Own?
Building a reliable bank statement parser from scratch requires:
- Handling hundreds of different PDF layouts across dozens of countries
- Parsing dates in many formats across languages
- Distinguishing debits from credits across different conventions
- Rebuilding logic every time any bank updates its format
An API abstracts all of this. You send a PDF, you get structured JSON.
Authentication
Get an API key from your dashboard (starts with pex_):
curl -X POST https://api.bankstatementparser.net/extract \
-H "X-Api-Key: pex_your_api_key" \
-F "file=@statement.pdf"
Python Integration
import requests
from pathlib import Path
class BankStatementParser:
BASE_URL = "https://api.bankstatementparser.net"
def __init__(self, api_key: str):
self.session = requests.Session()
self.session.headers.update({"X-Api-Key": api_key})
def extract(self, pdf_path: str | Path) -> dict:
with open(pdf_path, "rb") as f:
response = self.session.post(
f"{self.BASE_URL}/extract",
files={"file": (Path(pdf_path).name, f, "application/pdf")}
)
response.raise_for_status()
return response.json()
def extract_batch(self, pdf_paths: list) -> list[dict]:
return [self.extract(p) for p in pdf_paths]
# Usage
parser = BankStatementParser("pex_your_api_key")
result = parser.extract("statement.pdf")
print(f"Format: {result['bankKey']}")
print(f"Pages: {result['pageCount']}")
print(f"Transactions: {len(result['transactions'])}")
Node.js / TypeScript Integration
import FormData from 'form-data';
import fs from 'fs';
interface Transaction {
date: string;
description: string;
amount: number;
balance: number;
}
interface ParseResult {
bankKey: string;
pageCount: number;
transactions: Transaction[];
}
async function parseStatement(filePath: string): Promise {
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
const response = await fetch(
'https://api.bankstatementparser.net/extract',
{
method: 'POST',
headers: {
'X-Api-Key': 'pex_your_api_key',
...form.getHeaders(),
},
body: form as unknown as BodyInit,
}
);
if (!response.ok) {
throw new Error(Parse failed: ${response.status} ${response.statusText});
}
return response.json();
}
Error Handling
import requests
def safe_extract(pdf_path: str, api_key: str) -> dict | None:
try:
response = requests.post(
"https://api.bankstatementparser.net/extract",
headers={"X-Api-Key": api_key},
files={"file": open(pdf_path, "rb")},
timeout=60
)
match response.status_code:
case 200:
return response.json()
case 402:
print("Monthly quota exceeded — upgrade your plan")
case 415:
print("File is image-based (OCR not yet supported)")
case 422:
print("Could not parse this format")
case 429:
print("Rate limited — slow down requests")
case _:
response.raise_for_status()
except requests.Timeout:
print("Request timed out — file may be too large")
except requests.ConnectionError:
print("Connection error")
return None
Webhook Integration
For async processing (large files, high-volume workflows):
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
def submit_async(pdf_path: str, webhook_url: str):
return requests.post(
"https://api.bankstatementparser.net/extract",
headers={
"X-Api-Key": "pex_your_api_key",
"X-Webhook-Url": webhook_url,
},
files={"file": open(pdf_path, "rb")}
).json()
@app.route("/bank-callback", methods=["POST"])
def handle_result():
data = request.json
transactions = data["transactions"]
format_key = data["bankKey"]
print(f"Received {len(transactions)} transactions for format {format_key}")
return jsonify({"ok": True})
Response Schema
{
bankKey: string; // e.g. "bank_v1", "format_v2"
pageCount: number; // number of PDF pages processed
transactions: Array<{
date: string; // ISO 8601: "2026-05-15"
description: string; // raw transaction description
amount: number; // negative = debit, positive = credit
balance: number | null; // running balance (null if not in PDF)
}>;
}
Rate Limits & Quotas
| Plan | Pages/month | Requests/min |
|------|-------------|--------------|
| Free | 50 | 10 |
| Starter | 500 | 30 |
| Professional | 3,000 | 60 |
| Enterprise | 15,000 | 200 |
Get Your API Key
[Create a free account →](https://bankstatementparser.net/en/register) — 50 pages/month free, no credit card.