Skip to main content
Moneyline
All guides
Beginner5 minGetting started

Parse your first bank statement

From an API key to typed JSON with a reconciled balance, in about five minutes.

This walks through submitting one PDF and reading the result. By the end you will have typed transactions and a reconciliation check that tells you whether to trust them.

Get an API key

Create an organization in the dashboard and issue a key from Settings. Keys are scoped: for this guide a read-write key on documents is enough, and you should not use a key with broader scopes than the task needs.

bashbash
export MONEYLINE_API_KEY="sk_live_..."

# Self-hosting? Point at your own instance instead.
export MONEYLINE_BASE_URL="http://localhost:8080"

Submit the document

One request. type: auto runs classification first, which is what you want unless you already know the document type and want to skip it.

bashbash
curl -X POST "$MONEYLINE_BASE_URL/v1/parse" \
  -H "Authorization: Bearer $MONEYLINE_API_KEY" \
  -F "file=@statement.pdf" \
  -F "type=auto"

Parsing is asynchronous for anything large. The response carries a document_id and a status; poll it or, better, register a webhook so you are told rather than asking.

Read the result

The parsed document is typed per document type. A bank statement carries the account holder, the institution, opening and closing balances, and every transaction.

Trimmed for lengthjson
{
  "id": "doc_9f8e7d",
  "type": "bank_statement",
  "confidence": 0.994,
  "accountHolder": { "value": "R. Kumar", "confidence": 0.99 },
  "endingBalanceMinor": { "value": 4523167, "confidence": 1.0 },
  "transactions": [
    {
      "date": "2025-12-03",
      "descriptor": "AMZN MKTP US",
      "amountMinor": -14240,
      "category": "shopping"
    }
  ],
  "reconciliation": { "ok": true, "driftMinor": 0 }
}

Amounts are integers

Every monetary value is a minor-unit integer with a currency code, never a float. -14240 is $142.40 out. This is deliberate: binary floating point cannot represent most decimal amounts exactly, and money that is off by a fraction of a cent per row is a reconciliation bug waiting to happen.

Next

  • Register a webhook so results arrive instead of being polled.
  • Add enrichment to categorize transactions and verify income.
  • Route low-confidence fields to a review queue rather than accepting them.

Keep going

Run it yourself

Everything in this guide works against the open-source stack. Clone it, or start on the hosted API.