# Nutshell Tax API

This guide provides an integration overview of the Nutshell Tax API. It explains how filer, recipient, and form resources are created and validated and how to prepare recipient statements and submit tax filings.
Use this guide to understand the platform workflow and the sequence of API operations required for an integration. This guide reflects the [current OpenAPI specification](../../api-releases/2026-09-30/nutshell_tax.bundled.openapi.yaml), which is the source of truth for its endpoints, fields, request requirements, and responses.

> This is a product guide, not tax advice. IRS and state rules change. Confirm filing obligations and deadlines with current official instructions and your tax advisers.

## Example use case

Acme Holdings is preparing its Form 1099-NEC reporting. This guide follows one representative nonemployee-compensation record through the complete workflow.

At year end, Acme needs to:

1. identify itself as the filer
2. identify Jordan as the recipient
3. confirm that names and TIN information are usable
4. create the Form 1099-NEC record
5. provide the recipient statement required for tax reporting
6. file the same tax information with the IRS and any required states
7. monitor rejections, warnings, and corrections.

In the examples below, **Acme Holdings** is the filer, and **Jordan Lee** is the recipient.

Nutshell models that work like this:

```text
Acme Holdings                 Jordan
    │                                │
    ├── Filer                        └── Recipient
    │                                    └── Form 1099-NEC
    │
    └── Prepare snapshot
          ├── review statement ── publish ──> Jordan
          └── review filings ──── submit ────> IRS / state
```

The statement and filing use the same underlying form, but they serve different audiences:

- A **statement** is the recipient's tax document.
- A **filing** is the information return sent to a tax authority.

Preparing creates a safe review point. Publishing a statement or submitting a filing is the consequential step.

## What data you send to Nutshell

At a high level, Nutshell needs three layers of tax information:

```text
Filer: Who is reporting?
  └── Recipient: Who is the tax form about?
        └── Form: What happened, and what belongs in each form box?
```

### 1. Filer information


> **Terminology:** This guide uses **filer** for the business responsible for the tax reporting. Depending on the IRS form, that business may be labeled the filer, payer, broker, issuer, or another form-specific role. In the Tax API, all of these roles use the `filer` resource and filer endpoints.

The **filer** is the business responsible for reporting. Its form-specific role may be described as a broker, payer, withholding agent, issuer, or another term.

You generally provide:

- the filer's legal name and TIN
- domestic or foreign mailing address
- phone number and contact information
- state registration or other specialized information when it applies.

This information is entered once and reused across the filer's forms. Nutshell validates the field formats and reports whether the legal-name/TIN pair matches IRS records.

### 2. Recipient information

The **recipient** is the customer, payee, or other party whose tax information is being reported.

You generally provide:

- legal name
- TIN, when available
- mailing address
- relevant facts such as foreign status

The recipient is also entered once and reused across that recipient's forms. Nutshell checks the field formats and reports the legal-name/TIN matching result. A mailing address is required.

Whenever possible, use the stable customer ID from your system as the recipient `id` in Nutshell. For example, if Acme identifies Jordan as `contractor-8827`, it should create her with `"id": "contractor-8827"`. Acme can then use the same identifier in both systems without maintaining a separate ID mapping.

#### How W-9 and W-8 information maps to a recipient

A W-9 or W-8 is source documentation collected from the customer. It helps the filer decide how the customer should be treated for tax reporting. 
| Customer documentation | Information used in the API | API fields |
|---|---|---|
| Form W-9 for a U.S. person | Legal name, business or disregarded-entity name when applicable, U.S. TIN, and mailing address | `name`, `tin.taxpayer_id`, `tin.type`, and `mailing_address` |
| Form W-8 series for a foreign person or entity | Name, address, and TIN information when applicable | `name`, `mailing_address`, and `tin` when required |
| W-8 information needed for Form 1042-S | Country of tax residence, chapter 3 and chapter 4 status, GIIN, foreign TIN, and limitation-on-benefits category when applicable | `foreign_status.country`, `chapter_3_status`, `chapter_4_status`, `giin`, `foreign_tin`, and `lob_category` |

Use the customer documentation applicable to the recipient. Form W-9 supplies the TIN and certifications of a U.S. person. See the [IRS Instructions for the Requester of Form W-9](https://www.irs.gov/instructions/iw9).

The W-8 series covers several types of foreign persons and claims, so the correct certificate and reporting treatment depend on the customer's circumstances. A W-8 does not automatically mean that Acme should create a 1099. Acme first determines the applicable withholding and reporting obligation. The API's `foreign_status` object is only used when the recipient will receive Form 1042-S. Omit it for a recipient who will not receive Form 1042-S. See the [IRS instructions for requesters of Forms W-8](https://www.irs.gov/instructions/iw8).


### 3. Form and box information

The **form** describes the reportable event. It names the tax year and form type, then carries the values that belong in that form's boxes.

For example, a 1099-NEC may include:

- nonemployee compensation
- direct-sales reporting when applicable
- federal tax withheld
- state and local amounts when applicable
- account number and second-TIN-notice indicator

Names, TINs, and addresses are not repeated inside every form. Nutshell combines the form's box information with the filer and recipient records when it builds the recipient statement and government filing.

### 4. `_client` metadata

`_client` is optional metadata from **your own system**. It is not an IRS form box. When your system already has a stable identifier for a filer, recipient, or form, use that value as the resource `id` when possible. Use `_client` for additional workflow and source metadata that is useful for filtering or reconciliation.

For example:

```json
{
  "_client": {
    "filer_id": "acme-holdings",
    "batch_id": "2026-year-end"
  }
}
```

These values can help you:

- connect a form to the transaction or payment that created it
- group records into a processing batch
- reconcile records belonging to the same business batch.

The example above is recipient metadata the client can use when listing or reconciling records. A form can separately store a value such as `"source_record_id": "nec-2026-000417"` in its own `_client` object.

For new integrations, do not duplicate the stable recipient ID in `_client.customer_id` unless your workflow has a specific reason to do so. The recipient `id` should be the primary connection to the customer record. `_client.customer_id` remains useful as a fallback for older records that were created with a Nutshell-generated ID.

Collection filters can use `_client` values to find Acme's records later. Actions do not accept a recipient filter; an action applies to the prepared snapshot for the tax year selected in the request path. To keep Acme's records easy to reconcile, the metadata includes its filer ID and batch ID:

```text
_client.filer_id == "acme-holdings" && _client.batch_id == "2026-year-end"
```

Keep `_client` small and consistent. The complete object is limited to 1 KB. Reuse the same key names and value types across records so filtering stays predictable. Do not put required tax-form information only in `_client`. Information that must appear on a statement or filing belongs in the filer, recipient, or form fields defined by the schema.

`_client` can be attached to filers, recipients, and forms. Changing it counts as changing that resource, even though it does not change the form's tax-box data or restart the filing lifecycle.

### When validation happens

Nutshell validates the combined data in stages:

1. **When data is sent:** required fields, formats, lengths, and allowed values are checked.
2. **After a filer or recipient is created:** the legal-name/TIN pair begins in `AWAITING_MATCHING`.
3. **When a snapshot is prepared:** Nutshell captures the tax-year data, prepares statements and filings, runs TIN matching, checks whether the filer, recipient, and form-box information work together, and returns errors or warnings in `problems`.

This means a request can be accepted because it is correctly formatted and still need correction later because the tax information is incomplete or inconsistent.

## 1. Connect to Nutshell

Nutshell provides a client ID and client secret for connecting to the customer-facing API.

### Exchange a secret for a short-lived token

The secret is not sent to the Tax API. First, exchange it for a temporary access token. Applications should read `expires_in` and request a new token before or after expiration.

**Staging authentication URL\***

Use the staging token endpoint supplied by Nutshell:

```text
https://auth.dev.nutshelllabs.tech/realms/taxclient-demo/protocol/openid-connect/token
```

Set the client ID and the secret Nutshell provided:

```bash
export NUTSHELL_CLIENT_ID="ID"
export NUTSHELL_CLIENT_SECRET="SECRET"
export NUTSHELL_AUTH_URL="https://auth.dev.nutshelllabs.tech/realms/taxclient-demo/protocol/openid-connect/token"
```

Request a token:

```bash
export NUTSHELL_TOKEN="$(
  curl --silent --show-error --request POST \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode "client_id=$NUTSHELL_CLIENT_ID" \
    --data-urlencode "client_secret=$NUTSHELL_CLIENT_SECRET" \
    --data-urlencode 'grant_type=client_credentials' \
    "$NUTSHELL_AUTH_URL" |
  jq --raw-output '.access_token'
)"
```

Use the token on API calls:

```bash
--header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Repeat the token request on expiration. This client-credentials flow does not return a refresh token.

\* These are the staging URLs supplied by Nutshell. Authentication and Tax API base URLs vary by environment. Contact Nutshell for the URLs to use in another environment.

**Staging Tax API base URL\***

For the remaining examples, use the staging API base URL supplied by Nutshell:

```bash
export NUTSHELL_BASE_URL="https://taxapi.iris.demo.taxclient.nutshelllabs.tech"
export TAX_YEAR="2026"
```

## 2. Create the filer

Acme sends its legal name, TIN, mailing address, and phone number once. Every form beneath it reuses this identity.

```bash
curl --request POST "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "acme-holdings",
    "tin": {
      "taxpayer_id": "REPLACE_WITH_9_DIGITS",
      "type": "BUSINESS"
    },
    "name": {
      "type": "BUSINESS",
      "line1": "Acme Holdings Inc"
    },
    "mailing_address": {
      "type": "US",
      "line1": "120 Market Street",
      "city": "New York",
      "state": "NY",
      "zip_code": "10005"
    },
    "phone_number": "2125550100"
  }'
```

This guide uses a readable filer ID supplied by Acme:

```bash
export FILER_ID="acme-holdings"
```

The IRS matches the filer's legal name and TIN. Do not move to filing while the filer is `UNMATCHED`: a filer mismatch can affect the entire submission.

## 3. Add and validate the recipient

The recipient is the customer or payee who will receive the statement and whose information is reported to the IRS.

Jordan provided Form W-9 or equivalent certified information. Acme maps the legal name, TIN, and mailing address into the recipient record:

```bash
curl --request POST \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "contractor-8827",
    "tin": {
      "taxpayer_id": "REPLACE_WITH_9_DIGITS",
      "type": "INDIVIDUAL"
    },
    "name": {
      "type": "PERSON",
      "first_name": "Jordan",
      "last_name": "Lee"
    },
    "mailing_address": {
      "type": "US",
      "line1": "88 Hudson Street",
      "city": "Jersey City",
      "state": "NJ",
      "zip_code": "07302"
    },
    "_client": {
      "filer_id": "acme-holdings",
      "batch_id": "2026-year-end"
    }
  }'
```

```bash
export RECIPIENT_ID="contractor-8827"
```

### What Nutshell validates now

Nutshell immediately checks whether the data has the correct shape. Legal name and mailing address are required, a supplied TIN must contain nine digits and include its type, and names and addresses must follow the schema rules.

An invalid request returns `400 Bad Request` with details about what needs to be fixed.

### What TIN matching tells you

TIN matching checks the legal-name and TIN pair against IRS records. It is not a separate endpoint. The result appears on the recipient:

| TIN status | Meaning | Recommended action |
|---|---|---|
| `AWAITING_MATCHING` | The check is waiting or still running. | Check again later. |
| `MATCHED` | The IRS confirmed the pair. | Continue. |
| `UNMATCHED` | The IRS did not confirm the pair. | Check the source record and correct the name or TIN when necessary. |

```bash
curl \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/$RECIPIENT_ID" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Changing the legal name or TIN returns the recipient to `AWAITING_MATCHING`. Retrieve and update the same recipient rather than creating a new recipient for each correction. The next `prepareSnapshot` action runs matching again and prepares a new snapshot containing the correction.

An unmatched recipient requires review. A filer mismatch can affect the entire submission.

## 4. Add the tax form

The filer and recipient supply the identity blocks. The form supplies the transaction or payment details. The allowed fields and rules live in `Form1099NECBody` in the OpenAPI document.

### Example: Form 1099-NEC

Acme creates a Form 1099-NEC record with illustrative values.

```bash
curl --request POST \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/$RECIPIENT_ID/forms" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "nec-2026-000417",
    "tax_year": 2026,
    "data": {
      "type": "1099-NEC",
      "nonemployee_compensation": "12000.00",
      "account_number": "CONTRACTOR-8827"
    },
    "_client": {
      "source_record_id": "contractor-payment-417"
    }
  }'
```

```bash
export FORM_ID="nec-2026-000417"
```

Money values are JSON strings with two decimal places. Use `federal_income_tax_withheld` and `state_and_local_taxes` when they apply.

## 5. Prepare a snapshot for review

Creating a valid JSON object does not prove the tax return is ready. `prepareSnapshot` captures the current tax-year data and performs the deeper checks needed to prepare both filings and recipient statements.

The action applies to all filers, recipients, and forms in the tax year selected by the path. Omit the request body or send an empty JSON object.

You may run these actions repeatedly. However, only one prepare, publish, or submit action can be processing for a tax year at a time. Wait for the current operation to finish before starting another.

Preparation establishes what will be published or submitted. Changes and deletions made after `prepareSnapshot` are saved as newer resource input, but publish and submit actions continue to use the latest prepared snapshot. Run `prepareSnapshot` again when those changes should be included. If statements and filings must use exactly the same data, publish and submit the prepared snapshot before preparing a newer one.

Once a publish or submit action is accepted, a form included in that prepared snapshot can no longer be deleted. The restriction begins while the action is pending or processing and continues after it finishes, including after the form is updated. A form created after that snapshot remains deletable until a publish or submit action is accepted for a snapshot containing it.

```bash
curl --include --request POST \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/actions/prepareSnapshot" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

The response is `202 Accepted`: Nutshell has started the work, not finished it. The response body and `Location` header identify an operation to check.

```bash
curl "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/operations/REPLACE_WITH_OPERATION_ID" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Keep checking while the operation is `PENDING` or `PROCESSING`. Stop at `SUCCEEDED`, `FAILED`, or `CANCELED`.

The operation and the resource status are updated by separate parts of the platform. After an operation reaches a terminal status, a form or statement status may take additional time to appear. Continue retrieving the affected resources until their statuses reflect the result.

After the operation succeeds, retrieve Jordan's form:

```bash
curl \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/$RECIPIENT_ID/forms/$FORM_ID" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Accept: application/json"
```

Review these three parts of the response:

```json
{
  "id": "nec-2026-000417",
  "federal_filing_status": "AWAITING_FILING",
  "state_filings": [],
  "problems": []
}
```

- `federal_filing_status` shows whether the federal return is ready. `AWAITING_FILING` means it passed preparation. `AWAITING_CORRECTION` means it must be corrected.
- `state_filings` contains a separate status for every required state filing. Review each one because a federal return and its state returns can have different results.
- `problems` contains the errors and warnings found for the form. An `ERROR` blocks the filing named by the problem. A `WARNING` does not block filing, but it still requires review.

To inspect every form belonging to Jordan, list the collection instead:

```bash
curl \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/$RECIPIENT_ID/forms" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Review every form in `resources`. If `next_page_token` is not an empty string, request the next page by sending that value as `page_token` and continue until it is empty. Repeat this check for every recipient in the prepared tax-year snapshot.

The API retrieves a form as JSON. To obtain the filled recipient document as a PDF, use the statement document endpoint described below.

Changing a form's tax data returns its filing statuses to `AWAITING_PREPARATION`. 

## 6. Review and deliver recipient statements

When a filer is required to file a 1099, it generally must furnish the corresponding information to the recipient as well.

### Statement types

The API can return two statement kinds:

| API value | What it means | Representations available through the API |
|---|---|---|
| `STANDARD` | A filled recipient form that is not a consolidated 1099. | PDF |
| `SUBSTITUTE` | A consolidated 1099. | PDF, Nutshell statement archive, and Nutshell statement JSON |

A `SUBSTITUTE` statement is specifically a consolidated 1099. Every other statement is a `STANDARD` filled form. The prepared forms determine the read-only `kind`; the client does not select it in an API request.

Nutshell can separately configure cover pages, instructions, an 8949 summary, or supplemental files such as raw CSV/JSON and P&L reports.  

The snapshot prepared in step 5 includes recipient statements. After that operation finishes, list Jordan's statements:

```bash
curl \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/$RECIPIENT_ID/statements" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Retrieve each statement to see which forms it contains. A successfully prepared statement can be downloaded and reviewed before it is delivered:

```bash
export STATEMENT_ID="replace-with-statement-id"

curl "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/statements/$STATEMENT_ID/document" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Accept: application/pdf" \
  --output "$STATEMENT_ID.pdf"
```

Every statement has a PDF. A `SUBSTITUTE` statement also has archive and JSON representations with Nutshell-defined contents.

### Publish: deliver the statement

> Publishing is irreversible. `PUBLISHED` means the statement went to the recipient.

Publishing acts on all eligible statements in the latest prepared snapshot for the tax year:

```bash
curl --include --request POST \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/actions/statements/publish" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Confirm that each intended statement has `status: "PUBLISHED"` and a `published_at` time.

Published statements are historical records. Correcting the source form does not change a statement already delivered. A correction requires updating the form, preparing a new snapshot, reviewing the new statement, and publishing again. The original and corrected statements both remain available.

### IRS statement requirements to plan for

For 2026 reporting:

- Form 1099-NEC statements are generally due to the recipient by January 31 of the following year. Confirm the applicable date using the current IRS instructions.
- If a due date falls on a weekend or legal holiday, the next-business-day rule applies.
- A recipient's TIN may generally be truncated on an eligible recipient copy, but the filer's TIN may not.
- Electronic delivery must follow the applicable IRS consent or electronic-delivery rules, include all required information, notify the recipient, and keep the statement accessible for the required period.

See [IRS Publication 1099 (2026), Statements to Recipients](https://www.irs.gov/publications/p1099#en_US_2026_publink1000281818).

### Notification of statement availability

After Acme publishes Jordan's statement, Nutshell can send an electronic notice on Acme's behalf telling her that the statement is available. Nutshell can track whether the notice was delivered and whether Jordan accessed the document.

Nutshell can also send the statement by USPS mail. Paper delivery may be used when electronic delivery fails or when the recipient has selected paper delivery.

Notification methods, paper-delivery rules, and recipient preferences are configured with Nutshell. Contact the Nutshell team when planning how statement notification and delivery should work for your integration.

## 7. Submit filings to the IRS and states

Only submit filings that have been reviewed and are `AWAITING_FILING`.

```bash
curl --include --request POST \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/actions/filings/submit" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

A successful operation means Nutshell submitted the filings. It does **not** mean the IRS or state accepted them.

Responses arrive later on each form:

- `FILED` means the filing was submitted
- `AWAITING_CORRECTION` means preparation or an authority returned an error
- `problems` contains errors and warnings.

Keep monitoring after submission. A filing can move from `FILED` to `AWAITING_CORRECTION` when an authority responds.

State requirements and deadlines vary. Nutshell derives state filings from the form's data, and each state filing has its own status. Federal success does not guarantee state success.

See [IRS Publication 1099 (2026)](https://www.irs.gov/publications/p1099) for general filing rules and consult the current form-specific IRS instructions.

## Trace what was prepared, published, and filed

Use the snapshot `generation` to connect actions with the exact data they processed:

- The operations collection shows each prepare, publish, or submit action, including its `generation`, status, and timestamps.
- A single filer, recipient, or form response includes a `history` array of earlier generations, newest first. A form's current version and history retain the filing statuses and `problems` for each generation. A historical `FILED` status shows that generation was submitted.
- The statements collection shows which statements were created. A statement with `status: "PUBLISHED"` and `published_at` was delivered to the recipient.
- A single statement lists `forms`, and each entry includes the form `id` and `generation` used to build that statement. Match that generation to the form's current version or `history` to recover the exact source data.

Published statements remain as historical records. Updating a form creates newer resource input; it does not alter a statement already published or the filing results retained for an earlier generation.

## Update a recipient

Acme needs to correct Jordan's recipient information. Jordan is still the same recipient, so the integration updates `contractor-8827` rather than creating a new record.

First, retrieve the complete recipient:

```bash
curl --include \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/contractor-8827" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN"
```

Use the response as the starting point, then send the complete recipient with the correction:

```bash
curl --request PUT \
  "$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/contractor-8827" \
  --header "Authorization: Bearer $NUTSHELL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "contractor-8827",
    "tin": {
      "taxpayer_id": "REPLACE_WITH_CORRECT_9_DIGITS",
      "type": "INDIVIDUAL"
    },
    "name": {
      "type": "PERSON",
      "first_name": "Jordan",
      "last_name": "Lee"
    },
    "mailing_address": {
      "type": "US",
      "line1": "88 Hudson Street",
      "city": "Jersey City",
      "state": "NJ",
      "zip_code": "07302"
    },
    "_client": {
      "filer_id": "acme-holdings",
      "batch_id": "2026-year-end"
    }
  }'
```

`PUT` replaces the writable fields, so start with the current resource and include every writable value that should remain after the update. Run `prepareSnapshot` again when the corrected recipient should be included in a new snapshot.

## Annual workflows

The annual workflow is complete when the filer has delivered the required recipient statements, submitted the required federal and state filings, reviewed later authority responses, and corrected any errors. Nutshell keeps those steps connected to the filer, recipient, and form records that produced them, so a team can explain what was sent and follow up when something changes.

The integration is designed to be reused each filing season. For a new year, Acme creates or synchronizes the filer, recipients, and forms under that year's path. It can reuse stable IDs such as `acme-holdings` and `contractor-8827` because those resources belong to a different tax-year partition. Previously published statements, submitted filings, and operations remain under the path for the year that produced them.

The current API specification accepts tax year `2026`. For a later year, use the specification and form schemas released for that year rather than changing the tax year on an existing form. The overall cycle stays familiar:

```text
Select the new tax year
  → Create or synchronize filer and recipient data
  → Load the new year's forms
  → Validate and correct
  → Prepare one snapshot
  → Review and publish statements
  → Review and submit filings
  → Monitor authority responses
```

Using the same stable recipient IDs in both systems, along with consistent `_client` workflow values such as an annual `batch_id`, makes it easier to reconcile each filing season with the business records that produced it. That turns year-end reporting from a one-time project into a repeatable annual process.
