My year & tax report

Per-account month coverage, a Schedule C view with real IRS line numbers, and a cash-basis balance snapshot, built from your own bank/card statement documents.

Two read APIs, both scoped to your org and a calendar year, both computed fresh on every call from your documents' already-stored extraction results. Nothing is pre-aggregated or cached, so a corrected category or a newly uploaded statement is reflected immediately.

GET /v1/year-overview offers a free preview, except for a purchased year whose access has ended. The tax report, its export, and 1099 entries are part of the bookkeeping product: locked on Free, unlocked by an active Catch-Up purchase for the exact tax year asked about, or a live Autopilot/Business subscription for the current calendar year (402 TAX_REPORT_LOCKED otherwise). This is the same rule the app dashboard and MCP server enforce, not just this API.

Card balances use positive amounts for debt and negative amounts for credit. Balance snapshots group formatted account numbers by institution and account type. Invoices count as cash expenses only through a matched bank payment or a recorded payment_date. Unpaid invoices appear with a review_reason. Balance rows retain their source currency; only USD balances count in USD totals. Non-USD amounts stay out of USD totals and appear in uncategorized_transactions with currency and review_reason. The accountant CSV includes settled income with signed amounts, categories, document_id and row_index.

When a matched invoice was paid in a different year from bank posting, the expense appears once in the payment year. Its report row and accountant CSV include a note with both dates. The requested year still needs its own access.

Readable statement rows remain in the report when another row is unreadable. Unreadable amounts are null in uncategorized_transactions, with a review_reason, and blank in the accountant CSV.

Unknown transaction dates remain empty and need a date before they count in any tax year. Upload dates are never used as transaction dates.

Create received forms with POST /v1/form-1099. Required fields are an integer tax_year from 2000 through 2100,form_type of NEC or K, and a numeric amountfrom 0 through 999999999999 dollars. The optional payer_nameaccepts a string or null. Invalid fields return 400 before tax-year access is checked.

Catch-Up covers its purchased tax year for 12 months from payment settlement. Expired years lock until repurchased or covered by an active Autopilot plan. Files already downloaded remain yours. Autopilot, Business and active AppSumo codes cover the current calendar year. Page packs cover processing and raw extraction only. Accountant, QuickBooks, Xero, OFX and categorized statement-set exports require paid coverage for every included year.

Downloading these exports counts as delivery under the 30-day money-back guarantee. Tax report downloads and share links recheck current paid access for their tax year. Saved ZIP archives omit reports for years without access and always release your own original uploads, extraction results, categories and rules. A refund never preserves access to a paid report prepared earlier. While an automatic refund is pending, paid downloads in that business pause until it completes. Paid download attempts during this pause or lost access at release return 409 EXPORT_LOCKED. Failed or canceled refunds release the pause. Support reviews requests made after delivery under the same guarantee.

GET /v1/year-overview

Groups your bank_statement documents by account (as extracted, Arkrel has no separate "client" concept), and reports which months are covered vs. missing per account, reusing the exact same continuity engine POST /v1/statement-sets uses. Also totals income vs. spending by category and suggests one next step.

json
{
  "year": 2026,
  "accounts": [
    {
      "account_number": "****4471",
      "label": "Checking ending 4471",
      "months": [
        { "month": "2026-01", "label": "Jan 2026", "covered": true, "document_id": "doc_jan" },
        { "month": "2026-02", "label": "Feb 2026", "covered": false, "document_id": null }
      ],
      "months_covered": 1,
      "months_expected": 2,
      "document_ids": ["doc_jan"],
      "findings": []
    }
  ],
  "months_covered": 1,
  "months_expected": 2,
  "income_total": 5000,
  "spending_total": 120,
  "spending_by_category": [{ "category": "advertising", "label": "Advertising", "total": 120 }],
  "needs_review_documents": 0,
  "failed_documents": 0,
  "processing_documents": 0,
  "uncategorized_transactions": 0,
  "open_items": 1,
  "next_step": { "message": "Upload your Feb 2026 checking ending 4471 statement.", "action": "upload", "document_id": null, "account_number": "4471", "month": "2026-02" }
}

GET /v1/tax-report

A profit-and-loss statement, a Schedule C (Form 1040) view (every deductible category cites the real IRS line, e.g. line 8 "Advertising" or line 24b "Deductible meals"), the list of likely deductible expenses behind each line, and a cash-basis account-balances snapshot.

  • total_expenses / net_profit: the Cash P&L view, the full cash amount spent in every category. A refund or credit in the same category nets against the charge it reverses (a $100 charge and a $40 refund count as $60), rather than adding to the total; a refund's own deductible_expenses row shows a negative amount so the direction it actually moved is never lost.
  • schedule_c_lines: only lines with a nonzero total, sorted by line number. A category with a deductible-percentage limit (currently only meals, at 50% under the Instructions for Schedule C, line 24b, and IRC section 274(n)(1)) reports the deductible amount in total and the full cash amount in full_amount; every other line has full_amount: null because it equals total.
  • schedule_c_expenses / schedule_c_net_profit: the Schedule C view, the sum of schedule_c_lines (with any deductible-percentage limits already applied) and the resulting net profit. This differs from the Cash P&L totals whenever a limited category, such as meals, has spend.
  • uncategorized_transactions contains transactions awaiting category or source-information review. These rows remain outside income and expense totals while the relevant review item is unresolved.
  • confidence_label (on every deductible_expenses/uncategorized_transactions row): the ready-to-render label. "You set this" for a correction you saved yourself, "Standard rule" for a deterministic keyword-rule match, and a percentage ("Category confidence: 20%") only for a genuine low-confidence guess. Always show this verbatim; a rule match or a saved correction is never a probabilistic guess, so never recompute a percentage from confidence yourself.
  • excluded_transactions: transfers between your own accounts personal (non-deductible) spending, and asset or liability movements: also excluded from every total, shown separately so nothing you paid is silently dropped.
  • equipment_needs_review: a large one-time purchase (often equipment needing depreciation under Schedule C line 13 / Form 4562, unless it qualifies for the $2,500 de minimis safe harbor) held out of every deductible total until you resolve how it should be treated.
  • likely_needs_1099 lists potential 1099 payees from selected service-related expense categories, using the IRS reporting threshold for the report year: $600 for 2025 and earlier and $2,000 for 2026. The threshold is indexed for inflation for years after 2026; for a later year the report applies the most recent published threshold and names that year in threshold_tax_year. See the Instructions for Forms 1099-MISC and 1099-NEC. Payment platforms, marketplaces, and card processors (Upwork, Fiverr, PayPal, Venmo, Stripe, Square, and similar) never appear here: the Instructions for Forms 1099-MISC and 1099-NEC (irs.gov/instructions/i1099mec, "Form 1099-K") put the reporting duty for those payments on the payment settlement entity, on Form 1099-K, not on you.
  • form_1099: compares the 1099-NEC/1099-K amounts you enter (received as income) against gross_receipts. difference is null until entries has at least one form: before that there's nothing to compare yet, never a difference computed against zero.
  • balance_sheet: each account's latest statement closing balance at or before December 31: a cash-basis snapshot, not a formal (accrual) balance sheet. Each line carries the statement's own detected account_type ("bank", "credit_card", or null when not determinable). cash_total and credit_card_owed are separate sums, never combined: a bank account's balance is cash you have, a credit card's is money you owe. A line with account_type: null still appears in lines, but counts toward neither total.
json
{
  "year": 2026,
  "income_total": 5000,
  "total_expenses": 2520,
  "net_profit": 2480,
  "schedule_c_expenses": 2520,
  "schedule_c_net_profit": 2480,
  "schedule_c_lines": [
    { "category": "advertising", "label": "Advertising", "line": "8", "line_label": "Advertising", "total": 120, "full_amount": null, "note": null },
    { "category": "legal_and_professional", "label": "Legal and professional services", "line": "17", "line_label": "Legal and professional services", "total": 2400, "full_amount": null, "note": null }
  ],
  "deductible_expenses": [
    { "document_id": "doc_jan", "row_index": 3, "date": "2026-01-08", "description": "GOOGLE ADS 48213",
      "amount": 120, "category": "advertising", "category_label": "Advertising", "overridden": false,
      "confidence": 0.85, "confidence_label": "Standard rule", "reconciled": true, "source_page": null },
    { "document_id": "doc_jan", "row_index": 4, "date": "2026-01-09", "description": "SMITH LAW OFFICE",
      "amount": 2400, "category": "legal_and_professional", "category_label": "Legal and professional services", "overridden": false,
      "confidence": 0.85, "confidence_label": "Standard rule", "reconciled": true, "source_page": null }
  ],
  "uncategorized_transactions": [],
  "excluded_transactions": [],
  "equipment_needs_review": [],
  "likely_needs_1099": [
    { "payee_label": "SMITH LAW OFFICE", "total": 2400, "transaction_count": 1, "threshold": 2000, "threshold_tax_year": 2026 }
  ],
  "form_1099": {
    "tax_year": 2026, "entries": [{ "id": "f1099_1", "tax_year": 2026, "form_type": "NEC", "payer_name": "Acme Co", "amount": 3000, "document_id": null, "created_at": "2026-02-01T00:00:00.000Z" }],
    "total_reported": 3000, "gross_receipts": 5000, "difference": 2000,
    "citation": "Schedule C asks directly whether you made payments requiring a Form 1099."
  },
  "balance_sheet": {
    "as_of_year_end": 2026,
    "lines": [
      { "account_number": "****4471", "label": "Checking ending 4471", "as_of_date": "2026-01-31", "closing_balance": 5380, "document_id": "doc_jan", "account_type": "bank", "currency": "USD" },
      { "account_number": "****9902", "label": "Credit card ending 9902", "as_of_date": "2026-01-28", "closing_balance": 420.75, "document_id": "doc_card_jan", "account_type": "credit_card", "currency": "USD" }
    ],
    "cash_total": 5380,
    "credit_card_owed": 420.75,
    "note": "Cash-basis snapshot from each account's most recent statement closing balance at or before December 31."
  }
}

Review open items before using the report

Before using a client’s report for further bookkeeping or tax preparation, review the inputs that still affect it. Record the organization, calendar year, review date and supplied records in the firm’s workpaper. The report reflects the documents and decisions currently available in that organization.

Read open items beside the totals

Transactions awaiting category or source-information review remain outside income and expense totals. An unreadable amount or unknown transaction date also needs attention. Review the reason for each open item and decide what is needed next: a clearer statement, a receipt, a client explanation or a professional treatment decision.

Keep the possible effect visible to the person using the report. Where you cannot yet establish the amount or treatment, record the uncertainty and the next action rather than estimating a correction from the category name.

Check the reason for an exclusion

Review transfers, personal spending and asset or liability movements separately from income and expense totals. Check the supporting context for the exclusion. If equipment remains under review, obtain the purchase information needed for the appropriate professional to decide its treatment.

An unresolved transaction needs an answer. A confirmed exclusion needs a supported reason. Keeping those two review states separate helps the next reviewer understand which work remains.

Read the date behind each account balance

The account-balance snapshot uses each account’s latest available statement closing balance at or before year-end. Read the date attached to each account. If the latest source ends in September, request the later records needed for the engagement and keep that gap visible in the review note.

Read each balance with its account type and currency. The report totals USD bank balances and USD credit-card balances separately. Balances with an unknown account type or a currency other than USD remain visible outside those totals. Return to the statement-set coverage review when the available records do not cover the required period.

Keep a review note with the output

In the firm’s own records, keep the report year and review date, outstanding documents or questions, known effects on totals, and the person responsible for each next answer. Record which further work your firm must complete under the engagement.

Agree which of the available report downloads or sharing options fits the firm’s review process. Choose the accountant CSV when the reviewer needs individual income and expense rows, items needing review, and a separate list of excluded transactions. Keep the open-items note alongside it.

After the client supplies missing records or changes a category, review the updated report. Save a dated refreshed download and mark an earlier working copy as superseded so the review history remains clear. Use the updated information to decide the remaining professional work.

Can a report show totals while transaction questions are still open?

Yes. Review unresolved items alongside the totals. Transactions awaiting category or source-information review remain outside income and expense totals, while account balances come from statement closing balances. Establish the effect on the work before relying on the output.

What should we do after the client corrects a transaction?

Review the current report again and save a dated updated file when you need a download. Note the change in the firm’s workpaper and identify which earlier copy it supersedes. The client manages corrections in their own account.

GET /v1/tax-report/export

?format=csv (the categorized deductible-expense list), ?format=accountant_csv (every transaction, income and expense, including anything still needing review and any payees who may need a 1099, built for handing to a preparer), or ?format=pdf (the full report as a document).

PATCH /v1/tax-report/transactions/{document_id}/{row_index}

Corrects one transaction's category. Requires a write-scoped API key. row_index is the 0-based index into that document's own transactions table. Your correction always wins over the auto-suggested category on every future read, until you change it again.

http
PATCH /v1/tax-report/transactions/doc_jan/3 HTTP/1.1
Authorization: Bearer sk_live_...
Content-Type: application/json

{ "category": "office_expense" }

Share with your accountant

Existing shared reports and exports pause with HTTP 403 REPORT_UNAVAILABLE while their creator has a password without enabled authenticator protection. The viewer sees only "This report is not available right now." Account protection details are shown only to the signed-in creator. Access resumes after setup. Protected and passwordless creators keep access.

From the app (/app/tax-report), create a secure, expiring, read-only link to your report: no account or login required to view it. The link expires after 30 days, or revoke it anytime; creating a new link for the same tax year automatically revokes the previous one. There is no API to create this link programmatically by design: it's a deliberate, human action from the dashboard. Every public view and export checks access to that tax year again. If a refund or AppSumo revocation removes access, both GET /share/api/{token} and GET /share/api/{token}/export return402 TAX_REPORT_LOCKED immediately.