Bank statement extraction API

Lending, accounting, and personal-finance products all need transaction-level data from bank statements, but statements come as PDFs with bank-specific layouts and no consistent CSV export. The AIDataParser bank statement extraction API reads a statement PDF and returns account metadata plus a clean array of transactions: date, description, amount, direction, and running balance. You define the schema; the response conforms to it every time.

This turns a manual, error-prone data-entry job into a single API call. Whether it's a two-page checking statement or a dense multi-page business account, each transaction row is normalized into the same object shape, so your reconciliation engine, cash-flow model, or underwriting logic can consume it directly. Opening and closing balances come back as their own fields so you can validate that the extracted rows sum correctly.

For fintech builders, this is the ingestion layer that would otherwise take weeks of template engineering per bank. Send the statement by URL or upload, get structured JSON back for one credit, and lean on the confidence and review_needed signals to catch the odd page that didn't parse cleanly. Nothing is stored after the request, which matters when the input is sensitive financial data.

Fields you can extract from a bank statement

account_holderstring

Name on the account.

account_numberstring

Masked account number.

statement_periodstring

Date range covered.

opening_balancenumber

Balance at period start.

closing_balancenumber

Balance at period end.

transactionsarray

Date, description, amount, balance.

Example request

POST the bank statement by URL, upload, or base64, with a JSON Schema describing the output you want.

curl -X POST https://aidataparser.com/v1/parse/document \
  -H "Authorization: Bearer adp_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/statement.pdf",
    "schema": {
      "type": "object",
      "properties": {
        "account_holder": {
          "type": "string"
        },
        "account_number": {
          "type": "string"
        },
        "opening_balance": {
          "type": "number"
        },
        "closing_balance": {
          "type": "number"
        },
        "transactions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "date": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "amount": {
                "type": "number"
              },
              "balance": {
                "type": "number"
              }
            }
          }
        }
      }
    }
  }'

Example response

The data field is guaranteed to match your schema.

{
  "object": "parse.document",
  "data": {
    "account_holder": "Jordan Lee",
    "account_number": "•••• 8842",
    "opening_balance": 4200.15,
    "closing_balance": 3980.42,
    "transactions": [
      {
        "date": "2026-06-03",
        "description": "PAYROLL ACME",
        "amount": 2400,
        "balance": 6600.15
      },
      {
        "date": "2026-06-05",
        "description": "RENT",
        "amount": -1800,
        "balance": 4800.15
      }
    ]
  },
  "confidence": "high",
  "review_needed": false,
  "credits_charged": 1,
  "credits_remaining": 49
}

FAQ

Can it extract every transaction across a multi-page statement?

Yes. The transactions array captures each row across all pages, and returning opening_balance and closing_balance lets you verify the extracted rows reconcile.

Are amounts signed for debits and credits?

You control that through your schema — a common pattern is a signed amount field (negative for debits) or a separate direction enum. Either shape is validated on return.

Is statement data retained?

No. Statements are parsed in-request and discarded, so sensitive financial data isn't stored on our side. No credit is charged when a page fails to parse.

More document types