outputs

Numbers, lines, and the proof.

The engine is a computation and composition oracle, not filing software. Here is exactly what comes back, and the two things that do not.

Tax totals

Not only totals. calculate_tax returns the requested target (default us.federal.net_tax, negative for a refund) in integer cents, formatted, with every assumption it relied on. Any rule in the corpus can be a target: a Schedule 8812 credit, a Form 8995 deduction, an AMT figure.

Complete line sets

Federal: compute_return emits the Form 1040 bottom-line set, whole-dollar rounded, from transcribed W-2, 1099-R, SSA-1099, 1099-NEC, 1099-INT and 1099-DIV boxes: lines 1a, 9, 10, 11, 12e, 15, 16, 17 (AMT), 19, 22, 23, 24, 25d, 27a, 28, 32, 33, 34/37, plus Part IV withholding and the § 6654 penalty. Every other federal item is a calculate_tax target whose proof tree carries the worksheet arithmetic, not a printed line set.

State: compute_state_return emits the printed line set of the full-year-resident return for 31 states: every line the form's totals consume plus the schedule and worksheet lines those totals depend on. Vermont's IN-112 and IN-119, Delaware's two-column status 4, Montana's capital-gains worksheet. Ten more states compute the tax only. Part-year and nonresident returns are not composed anywhere.

compute_state_return · excerpt
{
  "ok": true,
  "asOf": "2025-12-31",
  "jurisdiction": "vt",
  "lines": {
    "1": "$62,000",
    "4": "$7,650",
    "5": "$5,300",
    "7": "$49,050",
    "8": "$1,576",
    …
  },
  "notes": [
    "Line 8: Vermont Tax Table (taxable income under $75,000; the table is mandatory)",
    …
  ],
  "corpusMerkleRoot": "sha256:…"
}

Federal scope in three buckets

Every federal item falls into exactly one of these. The coverage matrix lists the rules; this is the form-level view an integrator needs.

bucketwhat you gettoday
Complete line setMachine-readable printed-form lines, whole-dollar rounded, composed by the engine.Form 1040 bottom-line set (lines 1a to 37); 31 state resident returns.
Calculated target, no printed scheduleThe correct amount with a cited proof tree, which you place on the schedule yourself.Schedules A, SE, 1, 2, 3; Forms 8812, 8863, 8995, 6251, 8960, 8959, 2210, 8615, 8606, 8582, 2555, 8962, 8880, 8839; Schedule R; Schedule H (us.federal.household_employment_taxes: the tax, not the printed schedule lines); Form 1120 items.
Not coveredNo rule in the corpus; the engine refuses rather than approximates.Form 5695 (residential energy credits); Schedule 3 line 11 excess social security withholding; Form 1065 and Schedule K-1 preparation; Form 990; part-year and nonresident state returns; PDF and MeF output. Any of these can be scheduled as a priced deliverable.

Whole-dollar rounding, missing boxes, strict mode

compute_return follows the Form 1040 instructions on rounding: document amounts are summed in cents first, then every money input is rounded to the nearest dollar (50 cents up) before any computation, so line 15 and the Tax Table row are always the same number and document order can never change a result. The rounding is disclosed in documentNotes. calculate_tax computes in exact cents; it is a calculator, not a return.

A transcribed document that omits a box the return depends on (a W-2 without box 2) is treated as $0 and named in documentNotes. Pass strict: true to refuse instead: the response is NEEDS_FACTS with error.data.missing listing each box by path, so an unknown withholding is never finalised into a refund or balance due.

Completeness is machine-readable. Every compute_return and compute_state_return response carries complete: true | false and incomplete: an empty list, or one item per printed line this build does not compute, each with code (NOT_COMPUTED — no rule exists for the item, such as the Schedule 3 line 11 credit for excess social security withholding across several employers, reported with its amount and the Form 1040 lines it is missing from; or UNPUBLISHED — the rule exists but has no version valid on asOf, a tax year whose amounts the agency has not published, so the line holds a $0 placeholder and the item names the rule), the form, the line, the reason and the action. With strict: true the same situation is a refusal: INCOMPLETE_RETURN with the list under error.data.incomplete. Route on complete or the error code, never on the prose in notes.

Build identity

Every response carries versions: the engine, the composer (this server) and the corpus version with its Merkle root. Pin all three. The corpus changes when tax law or a state pack changes; the composer changes when a line-composition behaviour changes (this page is composer 0.5.0); the engine changes when evaluation semantics change.

Calculation proofs and citations

Every rule carries a statutory or form citation with a verbatim excerpt. Every computing response carries corpusMerkleRoot and artifactHash; pass includeProof: true to calculate_tax, compute_return, calculate_business_tax, calculate_fiduciary_tax or determine_dependent and the response also carries proof, the full artifact (about 200 KB): every applied rule, every input, every assumption, every rounding, hashed under the corpus Merkle root so the derivation verifies offline months later. On compute_return the artifact covers the us.federal.net_tax derivation (lines 9 to 24) and the response says so in proofScope; the other lines are separate cited targets on the same rounded facts, each available with its own tree through calculate_tax. The format is specified so a third party can write an independent checker: PROOF-FORMAT.md. explain_rule returns any rule's formula and law text on its own.

bash
# ask the API for the proof, then verify it byte for byte with the CLI
curl -s https://opentax.invaro.ai/v1/tools/calculate_tax -H "Content-Type: application/json" \
  -d '{"filing":{"filingStatus":"mfj"},"income":{"wages":120000},"credits":{"qualifyingChildren":2},"asOf":"2025-12-31","includeProof":true}' \
  | jq .proof > proof.json
npx -y @invaro/opentax verify proof.json

Rendered forms, PDF

No. The engine produces line values, not filled PDFs.

MeF XML

No. No MeF schema binding, no XML, no transmission. Your own MeF packaging consumes the line sets.

Two consequences for a filing pipeline

  1. Everything downstream of "here are the correct line values, with proof" is yours: the return document, the MeF payload, acknowledgments.
  2. Coverage is explicit and refusals are loud. Outside the corpus the call fails with a named code and says what is missing. It never estimates. The coverage matrix is the whole list.