> ## Documentation Index
> Fetch the complete documentation index at: https://zenofirm.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk operations

> Import, modify, void and delete many QuickBooks Online transactions at once, as one reviewed plan and one reversible run.

Everything a bulk import, bulk delete or bulk modify app does to a
QuickBooks Online file, Zeno does through the same door as any other write:
a plan the assistant prepares, a table a person reads, one approval, one
run, and one reversal that puts it back. There is no separate bulk tool to
buy or install, and there is no mode where the ledger changes without a
person having read exactly what will change.

This page is the map. Each job below names the tool an assistant calls and
what the approval table shows you.

## Import many transactions

`qb_plan_batch` takes any number of proposed postings, in names rather than
ids, and turns them into one plan: every kind QuickBooks Online can create,
including invoices, estimates, sales receipts, credit memos, refund receipts,
received payments, bills, bill payments by check or by card, checks, card
charges and credits, vendor credits, purchase orders, deposits, transfers,
journal entries and time. A spreadsheet or a QuickBooks Desktop file comes in
through [`qb_import_table` and `qb_import_iif`](/docs/cloud/imports), which read the
rows deterministically and hand the same plan to the same review.

What the table shows: every line, its resolved names and accounts, the reason
anything is held, and the names the plan will create first so the postings
can reference them. Duplicates of something already posted are held by name.

A sales form carries everything the printed document does. An invoice,
estimate, sales receipt, credit memo or refund receipt line takes
`billAddress` and `shipAddress`, the `email` it goes to (a comma-separated
list is fine), `sendLater` to queue it in QuickBooks Online's send list, a
`customerMessage`, and a `taxCode` on each line, by name against the
company's own tax codes. Two of these change what the reviewer approves
without changing the figure on the table, so the table says so: a taxable
line means QuickBooks Online adds sales tax on top of the plan's total, and
a queued send is one click from a customer's inbox. Any of these on a bill
or a check is refused by name rather than dropped.

A kind QuickBooks Online cannot create at all, such as a sales order, a
statement charge, an item receipt, an assembly build, an inventory transfer
between sites, a mileage entry or a US sales-tax payment, is refused on the
table with the QuickBooks Online alternative named, rather than failing later.

## Links between what you import

A bulk import is rarely a pile of unrelated documents. The plan carries the
three links QuickBooks Online has, and checks them before anything posts:

* **An invoice raised from an estimate.** `applyToLineNo` or `applyToTxnId`
  on an invoice names the estimate; QuickBooks Online closes it when the
  invoice lands.
* **A payment applied across documents and credits.** `applies` on a
  received payment lists the invoices it settles and the credit memos it
  uses up, each with the amount applied; on a bill payment, the bills and
  the vendor credits. The payment's own amount is the cash that moves, and a
  set that does not add up is blocked with the shortfall named.
* **A deposit of received payments.** A deposit line with `paymentLineNo` or
  `paymentTxnId` deposits that payment out of Undeposited Funds and names
  no account of its own.

A link by line number points at an earlier line of the same plan. If that
line did not post (excluded by the reviewer, or failed), the line that
links to it fails by name rather than posting unapplied.

## Modify many transactions

`qb_plan_cleanup` with a `select` whose action is `Modify` changes every
matching document under one approval. Two shapes of change ride the
selection, together or apart:

* **A patch**: the same header fields set on every match. The date, the due
  date, the document number, the private memo, the customer message, or any
  other header property; and the header's `location`, `class`, `customer`
  or `vendor`, by name, resolved against the ledger at plan time and shown
  on the table as the name it becomes.
* **A recode rule**: line coding moved from one name to another. Lines on
  account *A* move to account *B*; the same for a class, an item, or the
  customer a line is attributed to. Names, not ids. Only documents with a
  line on the *from* name are selected, and every other line on each
  document is restated exactly as it is. The rule's `paidFrom` moves the
  header account instead: the bank or card a purchase was paid from, the
  account a deposit went into. Moving a check onto a card account turns it
  into a card charge, and the table says so; a deposit cannot land on a
  card, and is refused.

The recode is what "the hundred checks coded to the wrong account" looks like
as one instruction. The table shows each document as the reviewer read it and
the coding it moves, as *account Automobile → Fuel*, not as a count of lines.
At apply, each document's lines are read live and rewritten in that instant;
a document that no longer carries the coding fails its own line and nothing is
sent for it.

```json theme={null}
{
  "select": {
    "action": "Modify",
    "kinds": ["Check"],
    "fromDate": "2026-01-01",
    "recode": { "account": { "from": "Automobile", "to": "Vehicle Fuel" } },
    "reason": "Coded to the retired account during the January import"
  }
}
```

A single document that needs its own change is an explicit `targets` line
with its own patch, or `qb_modify_transaction` on its own.

## Delete or void many transactions

The same tool with `select.action` of `Delete` or `Void`. The selection is a
filter: kinds, a date range, a counterparty name, or a line account. Every
match becomes a line, numbered in dependency order (a deposit before the
payments it holds, a payment before the invoice it pays) so the run does not
stall on a document QuickBooks Online will not release while another is
applied to it.

* **Delete** pages: a plan holds up to a thousand documents, the table says
  how many more matched, and the same selection after the plan applies takes
  the next batch. Emptying an old file is this loop, run until the selection
  is empty.
* **Void** keeps the number and the audit trail and is the right default
  wherever QuickBooks Online allows it (invoices, sales receipts, payments,
  bill payments and check purchases). A voided document stays on file and
  would match the same selection again, so a void can be selected only when
  everything matching fits in one plan; otherwise the plan says how many
  matched and the limit, and you narrow or raise it.

Each target is pinned to the revision the reviewer read. A document edited
between approval and apply is refused, not acted on.

## Import or retire many names

`qb_plan_names`, or the `lists` section of a batch, creates, changes or
retires accounts, customers, vendors, employees, items, classes, locations,
terms, payment methods, tax agencies and currencies in bulk, with names
already on file mapped to the existing row rather than doubled. QuickBooks
Online never deletes a name, so a retirement is a deactivation and comes back
the same way.

The last two carry rules of their own. A tax agency is created once and
queried: QuickBooks Online gives it no update and no way to retire it, so a
change or a retirement is refused on the table, and a reversal of a run that
created one says which agency stays. A currency's name is its three-letter
code and its identity, so it is never renamed; a plan naming one is checked
against a live read of the company's currencies rather than the copy on
file, and the run checks once more before it creates, so an agency or a
currency added in QuickBooks Online while the plan waited for approval is
used rather than doubled; a switched-off currency is turned back on with a
change rather than created again; and a company without a currency list is
refused the create, because turning multi-currency on cannot be undone.

## Attach documents in bulk

`qb_attach_documents` puts a receipt, a contract or any file onto many
transactions in one call. Attaching changes no figure in the books, so it is
one of the few writes that posts directly rather than through an approval
table; what it keeps of the plan loop is the journal: the call is one run,
each attachment a line of it with the document it landed on, a file
QuickBooks Online refuses fails its own line with the reason, and
`qb_reverse_run` removes exactly the attachments that run made and nothing
else.

## What a run records

A run's page in the console, and `qb_run_detail`, show every line with the
amount QuickBooks Online posted. Where it differs from what the plan said, as
when sales tax is added to an invoice or a bill payment settles a different
amount, the planned figure sits beside the posted one and the line says why.
The page downloads as a spreadsheet, and `qb_query` answers as one when
asked (`format: "csv"`), so a run or a question can go into a working paper
without being retyped.

## Reversal

Every run above is one `qb_reverse_run` away from undone. A modified or voided
document is restored onto its own row from the pre-image the run journalled
before it changed anything, keeping its number and links. A deleted document
can only be re-created under a new id, and the reversal says so per line.
Names a run created are deactivated.

<Note>
  The bulk apps you may be replacing act on a list of ids the moment you press
  go. A plan acts on the documents a person read, in the state they read them,
  and writes down what was there first. That is the whole difference, and it is
  why nothing here needs a separate approval mode.
</Note>
