Skip to content

Delete imported transactions

In the previous section, we learned how to use the ignore action to skip transactions we're not interested in. But what if you have already imported some transactions into your Beancount files and later realize they shouldn't be there? Simply changing the action from add_txn to ignore won't remove the transactions that were already written. You need the del_txn action to clean them up.

When you need del_txn

A common scenario is when you initially import all transactions without being selective, and later decide some of them shouldn't be in your books. For example, imagine you had imported the CREDIT BALANCE REFUND transaction before you learned about the ignore action. Your Beancount file now has an entry like this:

2025-01-25 * "Credit Balance" "CREDIT BALANCE REFUND"
  import-id: "loJ0nJ8BbaL2c3_haIP4JdDoKublBfrJ"
  import-src: "import-data/connect/chase/2025.csv"
  Liabilities:ChaseCreditCard                         -689.39 USD
  Assets:Cash                                          689.39 USD

If you simply change the action to ignore or remove the rule entirely, the already-imported transaction will remain in your Beancount file. The import engine doesn't touch existing transactions unless you explicitly tell it to. This is where del_txn comes in.

Using del_txn

The del_txn action tells the import engine to find and remove the matching transaction from your Beancount files based on the import-id metadata. Here's how you would use it to remove the credit balance refund:

  - name: Delete credit balance refund transactions
    match:
      extractor:
        equals: "plaid"
      desc: "CREDIT BALANCE REFUND"
    actions:
      - type: del_txn

When you run the import command, the engine will look at the import-id of the matched input transaction, find the corresponding Beancount transaction in your files, and remove it.

After the deletion is done, you can then switch the action to ignore to prevent these transactions from being imported again and from appearing in the Open transactions section:

  - name: Ignore credit balance refunds
    match:
      extractor:
        equals: "plaid"
      desc: "CREDIT BALANCE REFUND"
    actions:
      - type: ignore

Deleting multiple transactions at once

Just like ignore, you can use matching conditions such as one_of to delete multiple types of transactions in a single rule:

  - name: Delete incorrectly imported transactions
    match:
      extractor:
        equals: "plaid"
      desc:
        one_of:
          - "CREDIT BALANCE REFUND"
          - "AUTOPAY PAYMENT"
    actions:
      - type: del_txn

Custom import-id for deletion

As we covered in the step-by-step example, the import engine identifies transactions by their import-id metadata. By default, the import-id is determined by the extractor (e.g., {{ file | as_posix_path }}:{{ lineno }} or a transaction ID from the bank). You can read the document about unique import ID to learn more.

If you had used a custom id template when the transaction was originally imported, you need to specify the same pattern in the del_txn action so the engine can find the right transaction to delete. For example:

  - name: Delete transactions with custom import-id
    match:
      extractor:
        equals: "plaid"
      desc: "CREDIT BALANCE REFUND"
    actions:
      - type: del_txn
        txn:
          id: "custom-id-{{ file }}:{{ lineno }}"

The id value in the txn field must match the import-id that was used when the transaction was originally created. Otherwise, the engine won't be able to find and delete it.

The typical workflow

In practice, the del_txn action is usually a temporary step. The workflow looks like this:

  1. You realize some previously imported transactions need to be removed.
  2. You add a rule with type: del_txn for those transactions.
  3. You run the import command to delete them from your Beancount files.
  4. You change the action to type: ignore (or remove the rule if the transactions no longer appear in the input).
  5. You run the import command again to confirm everything is clean.

This way, del_txn handles the one-time cleanup, and ignore keeps things tidy going forward.