Walkthrough for terminal people

Inbox to Monarch: extract a card statement with Claude Code

Your card issuer emails you a PDF once a month. Monarch wants a CSV with its own columns. The gap between those two facts is usually twenty minutes of manual data entry or a converter site you have to trust with your statement. It does not have to be either. If you already live in Claude Code, the whole thing is two prompts typed into a terminal you already have open.

1GmailThe statement arrives as a PDF attachment
2Your machineClaude Code downloads it, and unlocks it if the issuer set a password
3MatchLedgerRows come out of the PDF and are checked against the statement totals
4A CSVWritten in your app's column shape, dates and signs included
5MonarchImport it. Or send the same rows to QuickBooks Online
You type two prompts. Steps 1 and 2 are the Google Workspace CLI running in your shell, step 3 is the MatchLedger MCP server, and steps 4 and 5 land in whichever app keeps your books.

What you need first

Two connections: the Google Workspace CLI so Claude Code can reach your Gmail, and the MatchLedger MCP server so it can extract the statement. Both are one-time setup and take about ten minutes. Set them up here, then come back.

The whole session

Below is a run against a statement we made up so we could publish it: Northgate Community Bank, a fictional bank, billing a fictional cardholder for a month of groceries, subscriptions and one trip. The card is invented. The results underneath it are not. That PDF went through the same production MatchLedger every account uses, and the numbers quoted here are what came back. You can download the statement and get them yourself.

Ask for the whole thing at once.

Name the app you are importing into right here in the first sentence. That one clause is what turns a pile of rows into a file Monarch will take without a mapping step:

In Claude Code

Find the newest Northgate Visa statement in my Gmail, unlock the PDF, upload it to MatchLedger as a credit card statement, and write the transactions out as a CSV in Monarch's import format.

Claude Code

Found one message from Northgate dated August 25 with a two-page PDF attached. It is password protected, so I unlocked it with the last four of the card and saved the plain copy locally.

Uploading to MatchLedger now as a credit card statement. Extraction runs in the background; a two-page file like this is usually under a minute.

gws gmail users messages list --params '{"userId":"me",
  "q":"from:northgatecb.example has:attachment filename:pdf newer_than:60d"}'

gws gmail users messages attachments get --params '{"userId":"me",
  "messageId":"1a07489...","id":"ANGjdJ_44Hlb..."}' --output stmt.pdf

Claude Code

Extraction finished. Here is what came back:

Card issuerNorthgate Community Bank, read off the statement
Statement periodJuly 26 to August 25, 2026
Rows extracted29 of 29, including the payment, the refund, the FX fee and the interest
Balance checkVerified, zero discrepancy
ReferenceEXT-Y2YMG2

Reading the PDF is the part MatchLedger does. It takes the file, works out which rows on the page are transactions, and returns dates, descriptions and signed amounts, whether the statement carries a text layer or is a scan of a paper page. It does not care which bank or which country the statement came from. See how format support works.

The balance check is the line worth reading

Twenty-nine rows came out because twenty-nine rows went in, and MatchLedger proves that rather than asserting it: it adds up the transactions it extracted and reconciles the total against the statement's own previous and new balance. On this file the previous balance of 1,482.16 plus a net 1,306.76 lands exactly on the printed new balance of 2,788.92, so nothing was dropped, duplicated or misread. A missed row would move that number and the check would fail. How the verification works.

That is the difference between a converter and something you would put in front of an accountant. Any tool can hand you a CSV. The question is whether you can tell it is complete without checking it by hand.

The CSV comes out in Monarch's shape.

Because the first prompt said Monarch, this arrives ready to import rather than as a generic table you then have to rework:

Claude Code

Done. 29 rows in Monarch's eight-column shape, dates as MM/DD/YYYY, charges negative and the payment positive, account labelled from the statement header.

DateMerchantCategoryAmount
07/26/2026TRADER JOES #452 PORTLAND ORFOOD-86.42
07/27/2026SPOTIFY USA NEW YORK NYENTERTAINMENT-11.99
08/04/2026PAYMENT - THANK YOU - MOBILEPAYMENT1450.00
08/12/2026RETURN - AMAZON MKTPL*QQ81M AMZN.COM/BILL WASHOPPING47.20
08/20/2026KLM ROYAL DUTCH AIR AMSTERDAM NL (EUR 205.00)TRAVEL-238.44
08/25/2026INTEREST CHARGE ON PURCHASESINTEREST-34.62

Six of twenty-nine rows shown. Account, Original Statement, Notes and Tags are the other four columns.

Those columns are not something the agent invented on the spot. MatchLedger publishes the import shape for each destination it supports, including the date format and which way the signs point, so a card charge lands as a charge rather than a refund. Monarch, QuickBooks Online, Xero, YNAB, Wave, FreshBooks and Zoho Books each have their own. See the export formats.

Monarch will do its own categorising on import using your rules, so treat the Category column as a starting point rather than an answer. The columns that have to be right are the date, the amount and its sign, and those are.

Forgot to say which app?

Leave the destination out of the first prompt and you get a reasonable generic CSV, which is not the same thing as one Monarch will take. Nothing is lost: the rows are already extracted, so ask again and the file is rewritten in seconds.

Follow-up

Write those same transactions out again as a CSV in Monarch's import format.

Look at it before you import it.

Optional, and worth thirty seconds the first few times. Since the Workspace CLI is already connected, the file can go straight to Drive as a spreadsheet:

In Claude Code

Put it in a Google Sheet so I can eyeball it before I import.

Claude Code

Uploaded and converted. Header plus 29 rows, and the raw CSV upload used for the conversion is in the trash so only the Sheet is left in your Drive.

gws drive +upload northgate-visa-2026-08-25.csv

gws drive files copy --params '{"fileId":"17KCFq..."}' \
  --json '{"name":"Northgate Visa 2026-08-25",
            "mimeType":"application/vnd.google-apps.spreadsheet"}'

Import into Monarch.

The only part that is not the terminal. In Monarch, open the account you are importing into, choose to upload a transaction file, and pick the CSV. Monarch reads the eight columns without any mapping step because they are already the ones it asks for, then runs your rules over the merchant names.

Spot check the payment row. On a credit card it is the one line that points the other way, and it is the fastest way to see that the signs came through correctly.

The same run, pointed at QuickBooks Online

Nothing above is Monarch-specific except the last clause of the first prompt. Ask for a QuickBooks Online credit card CSV instead and the same 29 rows come out in QBO's three-column shape, which is all QuickBooks accepts for a card import: date, description, and one signed amount with charges negative.

Here is that file, from the run described above, as a public spreadsheet. Tab one is the QuickBooks shape, tab two is the Monarch shape, and the Read me tab records where the numbers came from:

View only, no sign-in. Download the PDF, run it through your own connection, and the rows you get should match the sheet line for line.

Worth knowing if you are moving a card into QuickBooks: QBO reads a credit card CSV with charges negative and payments positive, the same direction as a bank import, and getting that backwards silently turns a month of spending into a month of refunds. MatchLedger stores the statement in that convention and writes it out that way. The full QuickBooks card guide covers the import screen itself.

If these are business books, do not stop at the CSV

Everything above is extraction: getting the statement out of a PDF and into a shape your app will take. For a personal card that is the whole job. For a card that belongs to a business, it is half of one, because importing transactions does not tell you the month is right. What does is reconciling the statement against what the books already say, so you can see the charge that was never coded, the payment recorded twice, and the fee nobody entered.

MatchLedger does that half from the same terminal. Upload the card statement and the account ledger for the same period, ask for a reconciliation, and you get the matches, the exceptions on each side, and a report you can hand to whoever asks. See how the two phases fit together.

Try it on your own statement

  1. Wire up the two connections once: Gmail and MatchLedger in Claude Code.
  2. Type the prompts from this page, with your own issuer name and your own app in the first one.
  3. Read the balance check before you import anything. If it did not verify, ask why rather than importing and finding out in the reconcile screen.
  4. If your issuer is not one MatchLedger has seen before, it is still read the same way, and you can ask us to add the format.

Common questions

Can Claude Code import my bank statement into Monarch Money?

It can do everything up to the import. Claude Code finds the statement in your Gmail, hands it to MatchLedger for extraction, and writes the transactions out as a CSV in Monarch Money's import shape. You upload that file in Monarch yourself, which takes about thirty seconds and is the only step that is not the terminal.

What CSV format does Monarch Money expect?

Eight columns: Date, Merchant, Category, Account, Original Statement, Notes, Amount, Tags. Dates are MM/DD/YYYY and a single signed Amount column carries the direction, so a card charge is negative and a payment is positive. MatchLedger writes that shape for you rather than leaving you to rearrange columns in a spreadsheet.

Do I need an API key for any of this?

No. The MatchLedger MCP server is added with one command and authenticates in your browser, and the Google Workspace CLI uses your own OAuth client and stores its token in your OS keyring. Nothing on either side asks you to paste a secret into a config file.

How do I know the extraction did not miss a transaction?

MatchLedger adds up the transactions it extracted and reconciles that total against the statement's own previous and new balance. On the sample statement published here, 1,482.16 plus a net 1,306.76 lands exactly on the printed 2,788.92, so the check passes with zero discrepancy. A dropped or duplicated row moves that number and the check fails, which is the point of running it before you import anything.

Does this work with a password-protected statement PDF?

Yes. Card issuers routinely lock the PDF with a date of birth or the last four digits of the card. Claude Code unlocks it on your own machine before anything is uploaded, so the password never leaves your laptop.

Can I send the same statement to QuickBooks Online instead?

Yes, and only the last clause of the prompt changes. Ask for a QuickBooks Online credit card CSV and the same transactions come out in the three columns QuickBooks accepts for a card import: date, description, and one signed amount with charges negative. Xero, YNAB, Wave, FreshBooks and Zoho Books each have their own shape too.

Keep reading

Connect it to the terminal you already have open.

Create a MatchLedger account

Or run the setup guide and let the connector open the sign-up page for you.

Claude and Claude Code are products of Anthropic. Monarch, QuickBooks Online, Gmail and Google Sheets are products of their respective owners. MatchLedger is not affiliated with or endorsed by any of them. Northgate Community Bank and the cardholder in the sample statement are invented; no real account, person or transaction appears on this page.