Skip to main content
Three requests that look like new features are answered by the tools you already have. Each recipe below was run on an ingested workspace holding the workbooks it names; the outputs are trimmed copies of the real responses. Upload and ingest the files first. Extract reads a workspace file by file_id (GET /v1/workspaces/{id}/files). Run SQL reads the table names that file metadata lists for the file.

Counterparty for each GL line

A general ledger sheet with Document Number and Document Description columns and no counterparty column. The description names the party after a dash (Vendor payment — Lantern Label Company — BILL-2025-0002), but a dash also introduces a place (Warehouse and office rent — Los Angeles and Commerce) or a date. Ask for the party and allow null:
Result on funky_town_general_ledger_2025.xlsx (671 posted lines, about 2.5 minutes, 39 credits):
All 671 lines came back in sheet order, and every non-null counterparty is a substring of its own document_description. 434 lines name a party; the other 237 (rent, payroll, depreciation, interest, closing entries) return null. Check the quote yourself with counterparty in document_description.
  • Citations. counterparty is quoted from the description cell, so the line’s row is its citation. In the run above only the first 20 of the 671 /gl_lines/N fields carried a citation (a sheet_range such as A7:I7 with the row’s text); the rest had none. To find any line’s row, look its document_number up with Run SQL on the ledger’s table.
  • Long ledgers. One call covered 671 lines. For a ledger much longer than that, split the request by account range in instructions (a spreadsheet has no pages, so page_ranges does not apply) and compare the line count with the sheet’s.

Signed trial balance with the rule

A trial balance that prints natural signs: assets and expenses positive when debit, liabilities, equity and revenue positive when credit, contra balances negative. Run SQL turns that into a debit-positive amount and returns the rule on each row. The account type comes from the account number here (1xxx asset, 2xxx liability, 3xxx equity, 4xxx revenue, 5xxx and up expense); change the CASE ranges if the chart of accounts differs.
Result on funky_town_trial_balance_2025.xlsx (26 accounts): rule reads debit-natural: signed = printed for the asset rows and credit-natural: signed = -printed for the liability and equity rows. Check the result with a second statement over the returned handle:
tb_sum was 0.0 over all 26 accounts: a signed trial balance nets to zero. Replace res_316297c88977 with the result.handle your first call returned. A sum that is not zero means a sign or an account type is wrong.
  • Citations. source_paths names the file, and result_citation.result_file.download_url fetches the whole result as parquet. To point at the printed account line, give the account number and name from the result.
  • Movement columns. This file also prints Debits and Credits movement columns. They are not the sign of Closing; the recipe signs the closing balance from the account type.
  • The sheet’s own convention. The statement does not read the sign convention the sheet prints in its header. If that line differs from the rule above, change the rule.

Printed total as a document field

A report whose last row is a printed TOTAL. Declare the lines and the total as separate fields, and say the TOTAL row is not a line:
Result on AR_Aging_2025-12-31.xlsx (3 credits):
The total is in document_total, the invoice row is the only entry in lines, and the total’s citation points at the TOTAL row (A4:F4). The printed total is not recomputed: compare document_total with the sum of lines[].open_balance and treat a difference as a finding about the report. In this file the two differ (23,282.50 against 6,435), because the printed report holds one invoice row under a larger total.