Inferensys

Prompt

Bank Statement Text to Transaction Records Prompt Template

A practical prompt playbook for using Bank Statement Text to Transaction Records Prompt Template in production AI workflows.
Operations team reviewing AI workflow automation on laptop, workflow builder visible, casual office setup.
PROMPT PLAYBOOK

When to Use This Prompt

Understand the job-to-be-done, ideal user, and critical boundaries for the bank statement repair prompt.

This prompt is designed for fintech platform engineers who receive unstructured or semi-structured transaction data from upstream systems—OCR pipelines, PDF parsers, or other models—that failed to produce valid, typed JSON. Its job is to convert that narrative text into a clean, predictable array of transaction records. The output contract includes normalized dates, a consistent debit-credit sign convention, a category classification, and a verified running balance. The primary goal is to repair malformed data before it enters a ledger, reconciliation engine, or compliance database, preventing downstream processing failures.

Use this prompt when you have a batch of bank statement text that needs to be ingested into a structured system but cannot be parsed by a deterministic script. It is ideal for scenarios where the source text has a consistent narrative pattern but lacks a machine-readable schema. The prompt's strict output schema and built-in verification logic (like running balance checks) make it a powerful post-extraction repair tool. However, you should not use this prompt for real-time payment processing, fraud detection, or any workflow where a hallucinated transaction could trigger an irreversible financial action without a human in the loop. It is a repair and normalization tool, not a real-time decision engine.

Before integrating this prompt, ensure you have a clear understanding of the expected input format and the downstream system's schema requirements. The prompt template uses placeholders like [INPUT] and [OUTPUT_SCHEMA] that you must populate with your specific data and contract. The next section provides the copy-ready template. After adapting it, you must build a robust implementation harness—including output validation, retry logic, and human review for high-value or high-risk transactions—as described in the 'Implementation Harness' section. Never deploy this prompt directly to production without automated checks that verify the mathematical consistency of the output.

PRACTICAL GUARDRAILS

Use Case Fit

This prompt template converts unstructured bank statement text into typed transaction records. It is designed for fintech pipelines that need consistent debit-credit sign handling and running balance verification before records enter a ledger or reconciliation system.

01

Good Fit: Clean OCR Text from Single Accounts

Use when: you have machine-readable text from a single bank statement with clear transaction lines, dates, and amounts. Guardrail: The prompt expects one account context per run. Batch processing should split statements by account first.

02

Bad Fit: Multi-Currency or Scanned Handwriting

Avoid when: statements contain mixed currencies without ISO codes, or the source is low-confidence handwriting OCR. Guardrail: Currency normalization and handwriting disambiguation require upstream preprocessing. This prompt assumes legible, single-currency input.

03

Required Inputs: Statement Text and Date Range

What to watch: The prompt needs the full statement text and an expected statement period. Without a date range, the model cannot validate whether transactions fall within the statement window. Guardrail: Always pass [STATEMENT_TEXT] and [STATEMENT_START_DATE] / [STATEMENT_END_DATE] as explicit inputs.

04

Operational Risk: Running Balance Drift

What to watch: A single misread transaction amount can cause the running balance to drift across all subsequent records, making the entire output unreliable for reconciliation. Guardrail: Implement a post-processing harness that recalculates the running balance from the first transaction and flags any row where the model's balance differs from the computed balance by more than a configurable tolerance.

05

Operational Risk: Debit-Credit Sign Inversion

What to watch: The model may misinterpret whether a transaction is a debit or credit, especially when statement formatting is ambiguous (e.g., parentheses for credits). Guardrail: Add a harness check that verifies the sign of each transaction amount matches the transaction type (debit/credit) and the direction of the running balance change. Flag inconsistencies for human review.

06

Not a Replacement for Bank APIs

What to watch: Teams may treat this prompt as a substitute for direct bank data feeds or OFX/CSV exports. Guardrail: This prompt is a repair and normalization tool for unstructured text, not a primary data ingestion path. Always prefer structured bank feeds when available. Use this only when statements arrive as unstructured text that cannot be obtained in machine-readable format.

PROMPT PLAYBOOK

Copy-Ready Prompt Template

A reusable prompt template with square-bracket placeholders for converting bank statement text into structured, validated transaction records.

This prompt template is designed to be copied directly into your application's prompt layer. It instructs the model to parse raw bank statement text and output a clean JSON array of transaction records. The template uses square-bracket placeholders for all dynamic inputs, constraints, and schemas, making it easy to wire into a production harness where these values are populated at runtime. The core instruction enforces strict output formatting, field-level type discipline, and a critical running-balance verification step that catches many common extraction errors before the data enters your ledger.

text
You are a precise financial data extraction engine. Your task is to convert the provided bank statement text into a structured JSON array of transaction records.

## Input
[INPUT]

## Output Schema
Return ONLY a valid JSON array of objects. Each object must conform to this exact schema:
[OUTPUT_SCHEMA]

## Constraints
[CONSTRAINTS]

## Examples
[EXAMPLES]

## Critical Verification Step
Before outputting the final JSON, perform this check internally:
1. For each transaction, calculate the expected running balance by applying the transaction amount to the previous running balance.
2. Compare your calculated running balance to the running balance stated in the bank statement text for that transaction.
3. If there is a mismatch, flag the transaction by setting the `"balance_verified"` field to `false` and include the `"calculated_balance"` in the output.
4. If the stated running balance is missing from the source text, set `"balance_verified"` to `null`.

## Risk Level
[RISK_LEVEL]

## Tools
[TOOLS]

To adapt this template, replace each square-bracket placeholder with the concrete values for your specific bank statement format and application requirements. The [OUTPUT_SCHEMA] should be a detailed JSON schema defining fields like transaction_date (ISO 8601 string), description (string), amount (number, positive for credits, negative for debits), category (string or null), and running_balance (number or null). The [CONSTRAINTS] placeholder is where you enforce rules like 'debit amounts must be negative' or 'dates must be parsed from MM/DD/YYYY format.' The [RISK_LEVEL] placeholder should be set to high for financial data, which signals your harness to enable additional validation, logging, and human review gates. After copying this template, the next step is to build the implementation harness that populates these placeholders and validates the model's output against your schema before it touches any financial system of record.

IMPLEMENTATION TABLE

Prompt Variables

Required and optional inputs for the Bank Statement Text to Transaction Records prompt. Each placeholder must be populated before the prompt is assembled and sent to the model.

PlaceholderPurposeExampleValidation Notes

[BANK_STATEMENT_TEXT]

Raw OCR or copy-pasted text from a bank statement containing transaction lines, dates, amounts, and running balances

01/15/2025 DEBIT CARD PURCHASE AMAZON.COM $42.97 Balance $1,203.45

Must contain at least one transaction-like line. Reject empty strings or text with no numeric amounts. Minimum 20 characters.

[STATEMENT_DATE_RANGE]

Expected date range for the statement period to help the model disambiguate transaction dates from other numbers

2025-01-01 to 2025-01-31

Must be two ISO-format dates separated by 'to'. Validate both dates parse correctly. Null allowed if statement text contains explicit period header.

[ACCOUNT_CURRENCY]

ISO 4217 currency code for the account to normalize amount fields and detect currency symbols in text

USD

Must match /^[A-Z]{3}$/. Validate against known currency code list. Default to USD if null but log warning.

[EXPECTED_TRANSACTION_COUNT]

Approximate number of transactions expected to detect truncation or major extraction failures

47

Must be a positive integer. Used for output count sanity check, not strict equality. Null allowed for variable-length statements.

[CATEGORY_TAXONOMY]

List of valid transaction categories for the model to classify each record into

["Groceries", "Utilities", "Dining", "Transfer", "Fee", "Income", "Shopping", "Uncategorized"]

Must be a JSON array of strings. Validate array is non-empty. Each category must be unique. Model output categories must match this list exactly or map to 'Uncategorized'.

[OUTPUT_SCHEMA]

JSON schema definition the model must conform to for each transaction record

{"type": "object", "properties": {"date": {"type": "string"}, "description": {"type": "string"}, "amount": {"type": "number"}, "type": {"enum": ["debit", "credit"]}, "category": {"type": "string"}, "running_balance": {"type": "number"}}, "required": ["date", "description", "amount", "type", "running_balance"]}

Must be valid JSON Schema draft-07 or later. Validate with a JSON Schema validator before prompt assembly. Required fields must include date, description, amount, type, and running_balance at minimum.

[RUNNING_BALANCE_CHECK]

Boolean flag enabling post-extraction arithmetic verification of running balance consistency

Must be true or false. When true, harness runs sequential balance verification: balance[i] + debit[i+1] or balance[i] - credit[i+1] must equal balance[i+1] within tolerance. Log failures as warnings, not hard errors.

[DEBIT_CREDIT_SIGN_CONVENTION]

Specifies whether debits are positive or negative in the source text to ensure sign consistency in output

debits_positive

Must be one of: debits_positive, debits_negative, inferred. When 'inferred', model determines convention from text. Harness validates all debit amounts have same sign and all credit amounts have opposite sign.

PROMPT PLAYBOOK

Implementation Harness Notes

How to wire the bank statement extraction prompt into a reliable production pipeline with validation, retries, and audit trails.

This prompt is designed to be called as part of a structured extraction pipeline, not as a standalone chat interaction. The typical flow is: raw bank statement text enters the system, the prompt converts it into a typed transaction array, and a post-processing harness validates the output before it reaches any database or downstream system. Because financial data is high-risk, the harness must enforce debit-credit sign consistency, running balance verification, and required field presence before accepting any record.

Model choice and invocation pattern: Use a model with strong JSON mode or structured output support (e.g., GPT-4o with response_format: { type: 'json_object' }, Claude with tool-use extraction, or Gemini with controlled generation). Always set temperature=0 to minimize variance in numeric fields. Call the prompt with the raw statement text injected into the [STATEMENT_TEXT] placeholder. If the statement exceeds the model's context window, chunk it by statement page or month boundary and merge results in the application layer, checking for duplicate transactions across chunks by matching date, description, and amount within a small tolerance.

Validation and retry logic: After receiving the model response, run a multi-step validator: (1) confirm the output is valid JSON with a transactions array, (2) verify every record has non-null date, description, and amount fields, (3) check that debit and credit values are mutually exclusive per record (one must be zero or null when the other is populated), (4) recalculate the running balance from the first transaction forward and compare against the model's running_balance field with a tolerance of ±0.01, and (5) flag any transaction where the sign of the net change doesn't match the direction of the balance movement. If validation fails, construct a repair prompt that includes the original statement text, the failed output, and the specific validation errors, then retry once. If the retry also fails, route the record to a human review queue with the raw statement, the failed extraction, and the validator error log.

Logging and audit trail: Log every extraction attempt—including the raw input, the model's raw output, validation results, and any retry attempts—to an append-only audit store. This is critical for fintech compliance and debugging. Include a pipeline_run_id and transaction_batch_id in every log entry so you can trace a single statement through extraction, validation, repair, and eventual ingestion. Never silently drop failed records; even rejected extractions should leave an audit artifact explaining why they were rejected.

Integration with downstream systems: Once a transaction batch passes validation, transform the records into your canonical transaction schema before writing to the ledger or database. Map the prompt's category field to your internal chart of accounts using a lookup table or a secondary classification prompt if the model's category doesn't match your taxonomy. For running balance verification, treat the model's running_balance as a cross-check against your system of record—never as the authoritative balance. The authoritative balance must come from the bank's official statement or API, with the extracted balance serving only as a reconciliation signal.

What to avoid: Do not use this prompt for real-time transaction processing or payment initiation. Do not skip the running balance verification step, even if the model appears confident—arithmetic errors are common in long transaction sequences. Do not store raw bank statement text in logs without redacting account numbers and PII first. And do not treat a passing validation as proof of correctness; sampled human review of extracted transactions should be part of your regular quality assurance cadence, especially for high-value or unusual transactions.

IMPLEMENTATION TABLE

Expected Output Contract

Defines the required fields, types, and validation rules for each transaction record extracted from bank statement text. Use this contract to build downstream parsers, database schemas, and validation harnesses.

Field or ElementType or FormatRequiredValidation Rule

transaction_date

string (ISO 8601 date)

Must parse to a valid date. Reject if month > 12 or day > 31. Normalize to YYYY-MM-DD format.

description

string

Must not be empty or whitespace-only. Length must be between 1 and 500 characters. Trim leading/trailing whitespace.

amount

number (decimal)

Must be a valid decimal number with up to 2 decimal places. Must not be zero. Sign must be consistent with [TRANSACTION_TYPE].

transaction_type

string (enum)

Must be exactly 'debit' or 'credit'. Validate that debit amounts are negative and credit amounts are positive per [SIGN_CONVENTION].

running_balance

number (decimal) or null

If present, must be a valid decimal. If [VERIFY_RUNNING_BALANCE] is true, validate that balance change equals transaction amount within 0.01 tolerance.

category

string or null

If present, must match one of the allowed values in [CATEGORY_LIST]. Null is allowed when category cannot be determined from description.

check_number

string or null

If present, must be a non-empty string. If extracted from description, verify it matches the pattern defined in [CHECK_NUMBER_PATTERN].

source_text

string

Must contain the exact substring from [INPUT_TEXT] that produced this record. Used for audit trail and human review. Must not be empty.

PRACTICAL GUARDRAILS

Common Failure Modes

Production failures when converting bank statement text to transaction records, and how to prevent them before they corrupt your ledger.

01

Debit-Credit Sign Inconsistency

What to watch: The model flips the sign on transactions—credits become debits or vice versa—especially when the statement uses ambiguous language like 'payment received' or 'withdrawal.' A single sign error can cascade into balance mismatches across the entire statement. Guardrail: Add a post-extraction harness check that verifies ending_balance = starting_balance + sum(credits) - sum(debits) for every statement. Flag any row where the running balance delta doesn't match the transaction amount sign.

02

Running Balance Drift

What to watch: The model extracts individual transactions correctly but the computed running balance diverges from the statement's printed running balance after several rows. This often happens when the model misses a transaction, duplicates one, or misaligns the balance column with the wrong row. Guardrail: Implement a row-by-row balance reconciliation check. After extracting all transactions, recompute the running balance from the first row and compare against the extracted balance at each step. Escalate any row where the delta exceeds $0.01 for human review.

03

Date Format Ambiguity

What to watch: The model misinterprets date formats—confusing MM/DD/YYYY with DD/MM/YYYY—or fails to parse relative dates like 'yesterday' or 'last Tuesday.' This is especially dangerous for statements crossing month boundaries or from international banks. Guardrail: Require the prompt to output dates in ISO 8601 format only. Add a validator that rejects any date not matching YYYY-MM-DD and flags dates that are in the future or more than 90 days in the past relative to the statement period.

04

Category Hallucination

What to watch: The model invents transaction categories that don't appear in the statement text—like labeling a generic 'ACH CREDIT' as 'Payroll' or 'Refund' without evidence. This contaminates downstream financial reporting and reconciliation. Guardrail: Constrain the prompt to only assign categories when the statement explicitly provides them. For uncategorized transactions, output null or "uncategorized" rather than inferring. Add a post-extraction check that flags any category value not present in the source text.

05

Multi-Line Transaction Fragmentation

What to watch: A single transaction split across multiple lines in the statement—common with detailed descriptions or multi-part entries—gets extracted as two separate transactions, inflating the record count and breaking balance calculations. Guardrail: Include few-shot examples in the prompt showing multi-line transactions merged into single records. Add a deduplication pass that merges adjacent rows sharing the same date and amount but with continuation descriptions, using the statement's line spacing or indentation as merge signals.

06

Currency Symbol and Amount Parsing

What to watch: The model misparses amounts containing currency symbols, thousand separators, or parentheses for negative values—turning ($1,234.56) into a positive number or dropping the decimal. This silently corrupts every downstream calculation. Guardrail: Enforce a strict numeric output format in the prompt: amounts must be decimal numbers with exactly two decimal places, no currency symbols, no thousand separators, and negative values must use a leading minus sign. Add a regex validator that rejects any amount field not matching ^-?\d+\.\d{2}$.

IMPLEMENTATION TABLE

Evaluation Rubric

Use this rubric to test the quality of structured transaction records generated from bank statement text before shipping to production. Each criterion includes a pass standard, a failure signal, and a concrete test method.

CriterionPass StandardFailure SignalTest Method

Field Completeness

All required fields (date, description, amount, category, running_balance) are present and non-null for every transaction

Missing fields or null values in required fields for any transaction record

Schema validation: parse output JSON and assert all required keys exist and are not null for each record in the array

Date Format Consistency

All date fields conform to ISO 8601 format (YYYY-MM-DD) and are parseable

Non-standard date formats, ambiguous dates (e.g., 01/02/2024), or unparseable strings

Regex pattern match against ^\d{4}-\d{2}-\d{2}$ for every date field; attempt Date.parse() and assert no NaN

Debit-Credit Sign Consistency

Debit transactions have negative amounts, credit transactions have positive amounts, and sign matches the transaction type description

Positive amount for a debit transaction or negative amount for a credit transaction; sign contradicts description

For each record, check if description contains debit/credit keywords; assert amount sign matches expected direction; flag mismatches

Running Balance Arithmetic

Each running_balance equals the previous running_balance plus the current transaction amount within a tolerance of 0.01

Running balance drifts from expected value; cumulative sum of amounts does not reconcile with stated running balance

Iterate through sorted records; compute expected_balance = prior_balance + amount; assert abs(expected_balance - running_balance) < 0.01 for each record

Category Assignment Validity

Every category field contains a value from the allowed enum: [INCOME, TRANSFER, PAYMENT, FEE, INTEREST, OTHER]

Category contains free-text, misspelled, or out-of-enum values; category is null or empty string

Assert category value is in the allowed enum set for every record; reject any record with non-matching category

Amount Precision

All amount fields are numeric with exactly two decimal places and no currency symbols or commas

Amounts contain currency symbols ($, €), thousand separators, or more than two decimal places

Parse each amount as float; assert no NaN; assert amount.toFixed(2) equals original string representation after stripping non-numeric chars except decimal point

Record Count Preservation

Number of output transaction records matches the number of transactions identifiable in the source text

Output contains fewer or more records than transactions present in the input statement text

Manual count of transactions in source text vs output array length; automated check: assert output.length equals expected count from ground truth or source parsing

Description Fidelity

Description field contains the original transaction description from the source text without hallucinated additions

Description contains merchant names, locations, or details not present in the source text; description is truncated or rewritten

String similarity check between source text segments and output descriptions; flag records where edit distance exceeds threshold or contains tokens absent from source

ADAPTATION OPTIONS

Adapt This Prompt

How to adapt

Use the base prompt with a frontier model (GPT-4o, Claude 3.5 Sonnet) and minimal post-processing. Focus on getting the core extraction working before adding validation layers. Remove the running balance verification step initially—add it once date parsing and amount sign conventions are stable.

Prompt snippet

code
Extract transactions from [BANK_STATEMENT_TEXT] as JSON.
Fields: date, description, amount, category, running_balance.

Watch for

  • Debit/credit sign inconsistency (deposits as negative, withdrawals as positive)
  • Date format drift across statement pages
  • Category hallucination when statement doesn't provide categories
  • Running balance not matching sequential transaction math
Prasad Kumkar

About the author

Prasad Kumkar

CEO & MD, Inference Systems

Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.

His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.