API reference
BankFlow v1 API
Parse bank statements programmatically. POST a PDF, CSV, XLSX, or JSON file, get structured JSON back. The same engine that powers the app, available over a simple REST API. API access is available on every plan, including free: usage is metered by your credit balance.
Authentication
Generate a personal access token (prefixed bnfw_) from the API settings in the app. Pass it as a bearer token on every request - including the OpenAPI endpoint.
Authorization: Bearer bnfw_your_api_key_here
Quickstart
Send a PDF, CSV, XLSX, or JSON file to /api/v1/parse and receive the parsed bank and transactions synchronously.
curl -X POST https://api.bankflow.app/api/v1/parse \ -H "Authorization: Bearer bnfw_your_api_key_here" \ -H "Content-Type: application/pdf" \ --data-binary @statement.pdf
const fs = require('fs');
const pdf = fs.readFileSync('statement.pdf');
const res = await fetch('https://api.bankflow.app/api/v1/parse', {
method: 'POST',
headers: {
'Authorization': 'Bearer bnfw_your_api_key_here',
'Content-Type': 'application/pdf',
},
body: pdf,
});
const { data, transactions } = await res.json();
console.log(data.bankName);
console.log(transactions);import requests
with open('statement.pdf', 'rb') as f:
pdf_bytes = f.read()
response = requests.post(
'https://api.bankflow.app/api/v1/parse',
headers={
'Authorization': 'Bearer bnfw_your_api_key_here',
'Content-Type': 'application/pdf',
},
data=pdf_bytes,
)
body = response.json()
print(body['data']['bankName'])
for txn in body['transactions']:
print(txn['date'], txn['description'], txn['amount'], txn['type'])Example response
{
"data": {
"id": 1042,
"fileName": "statement.pdf",
"status": "completed",
"bankName": "Bank of America",
"currency": "USD",
"transactionCount": 2,
"openingBalance": 25000.00,
"closingBalance": 109550.00
},
"transactions": [
{
"id": 90211,
"date": "2024-01-03",
"description": "UPI/SWIGGY/Food Order",
"amount": 450.00,
"type": "debit",
"category": "Food & Dining",
"tags": [],
"balance": 24550.00
},
{
"id": 90212,
"date": "2024-01-05",
"description": "SALARY CREDIT",
"amount": 85000.00,
"type": "credit",
"category": "Income",
"tags": [],
"balance": 109550.00
}
]
}Statements
Upload, inspect, delete, analyze, and export parsed statements.
/api/v1/statementsList statementsReturns paginated statements with processing status, bank, source, and transaction count.
Query
page, limit
status=processing|completed|failed
search, from, to
Response
{ data: Statement[], pagination }
/api/v1/statementsUpload and persist a statementAccepts multipart form-data (field file), or raw file bytes with an X-File-Name header: PDF, CSV, XLSX, or JSON. Parses synchronously and stores the statement plus transactions. Add ?include=transactions to embed the parsed transactions in the response.
Body
multipart/form-data → file
raw bytes (application/pdf or application/octet-stream)
Query
include=transactions → embed parsed transactions inline
Headers
X-File-Name (raw uploads)
X-PDF-Password (encrypted PDFs)
X-Column-Mapping (CSV/XLSX)
Non-ASCII header values: send raw UTF-8, or percent-encode and add <header>-Encoding: url
Limits
Max 50MB per file
/api/v1/parseParse and return transactionsOne-shot parse: POST a PDF (or CSV/XLSX/JSON file) and get the parsed transactions back inline, alongside the persisted statement, no follow-up call. Same auth, limits, and credit cost as the upload endpoint.
Body
multipart/form-data → file
application/pdf raw body
Response
{ data: StatementDetail, transactions: Transaction[] }
/api/v1/statements/detect-columnsPreview & auto-detect columnsFor CSV/XLSX uploads: returns the auto-detected column mapping along with the file's headers and a sample of rows, so you can confirm or override the mapping before importing. Nothing is persisted.
Body
multipart/form-data → file
raw bytes + X-File-Name header
Response
{ data: { headers, sampleRows, rowCount, mapping, detectionSource, confident } }
/api/v1/statements/:idGet statement detailsFetches one statement with processing status, balances, period, and metadata.
Path
:id = statement id
Response
{ data: StatementDetail }
/api/v1/statements/:idDelete a statementDeletes the statement and all associated transactions.
Path
:id = statement id
Response
{ success: true }
/api/v1/statements/:id/transactionsList statement transactionsReturns paginated transactions for a single statement with category, type, search, and date filters.
Query
page, limit
category, type
search, from, to
Response
{ data: Transaction[], pagination }
/api/v1/statements/:id/insightsGet financial insightsComputes income, expenses, savings, top categories, recurring payments, salary detection, and monthly cashflow.
Path
:id = statement id
Response
{ data: Insights }
/api/v1/statements/:id/exportExport a statementExports one statement as JSON, CSV, or XLSX with optional filters.
Query
format=json|csv|xlsx
category, type
search, from, to
Response
JSON envelope or file download
Transactions
Import transactions directly from structured data, and correct stored transaction metadata.
/api/v1/transactions/bulkImport transactions directlyImports a canonical JSON transactions payload, no source file needed. Send a raw array of transactions, or an object with statement metadata and a transactions array. Creates a statement to hold them and runs the same persist pipeline as a file upload (costs 1 credit).
Body
Transaction[]
or { bankName?, currency?, openingBalance?, closingBalance?, transactions: Transaction[] }
Transaction → { date, description?, amount? | debit?/credit?, type?, balance? }
Response
201 { data: Statement }
/api/v1/transactions/:idUpdate transaction metadataUpdates category, notes, and tags for a stored transaction.
Body
{ category?, notes?, tags?: string[] }
Response
{ success: true }
Webhooks
Events BankFlow delivers to endpoints you register. Each delivery is a POST with body { "event", "data" } and an X-BankFlow-Signature: sha256=<hmac> header: an HMAC-SHA256 of the raw body, keyed with your webhook secret. Verify it before trusting a payload. Deliveries are single-attempt; failures are logged and can be replayed.
statement.completedA statement finished parsing and its transactions are stored (lightweight, no transaction data).
data
{ statementId, fileName, transactionCount, bankName }
transactions.createdA statement finished importing: carries the full parsed transactions inline. Fires on every import (API upload, queued upload, Gmail auto-import), so it's how async flows receive their transactions.
data
{ statementId, bankName, transactionCount, transactions: Transaction[] }
statement.failedA statement could not be parsed. No statementId, nothing was stored; correlate by fileName.
data
{ fileName, error }
statement.deletedA statement (and its transactions) was deleted.
data
{ statementId, fileName }
transaction.updatedA single transaction was edited (category/notes/tags). Does not fire on import.
data
{ transactionId, statementId, category }
Webhook management
Endpoints to register, list, and delete webhook endpoints. For the events you receive and their payloads, see the Webhooks section above.
/api/v1/webhooksList registered webhooksReturns every webhook endpoint registered for your API key owner.
Response
{ data: Webhook[] }
/api/v1/webhooksRegister a webhookCreates a webhook endpoint and returns the generated signing secret once.
Body
{ url: string, events: string[] }
Response
{ data: { id, url, events, secret } }
/api/v1/webhooks/:id/rotateRotate signing secretGenerates a fresh signing secret for the endpoint and returns it once. The previous secret stops validating immediately, so update your verifier in the same step.
Path
:id = webhook id
Response
{ data: { id, url, events, secret } }
/api/v1/webhooks/:idDelete a webhookRemoves a registered webhook endpoint.
Path
:id = webhook id
Response
{ success: true }
OpenAPI
Machine-readable API specification for tooling and Swagger-style docs.
/api/v1/openapi.jsonRaw OpenAPI 3.0 specReturns the complete BankFlow v1 OpenAPI document as JSON.
Use cases
Swagger UI
SDK generation
Schema inspection
Response
OpenAPI 3.0.3 JSON document
Need the machine-readable spec?
The full OpenAPI 3.0 document is available at https://api.bankflow.app/api/v1/openapi.json for Swagger UI and SDK generation.