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, 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 1042-S reporting. This guide follows one representative payment record through the complete workflow.
At year end, Acme needs to:
- identify itself as the filer
- identify Jennifer as the recipient
- confirm that names and TIN information are usable
- create the Form 1042-S record
- provide the recipient statement required for tax reporting
- file the same tax information with the IRS and any required states
- monitor rejections, warnings, and corrections.
In the examples below, Acme Holdings is the filer, and Jennifer McNally is the recipient.
Nutshell models that work like this:
Acme Holdings Jennifer
│ │
├── Filer └── Recipient
│ └── Form 1042-S
│
└── Prepare snapshot
├── review statement ── publish ──> Jennifer
└── 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:
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
filerresource 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 Jennifer as customer-8827, it should create her with "id": "customer-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.
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.
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 1042-S may include:
- income code and gross income
- chapter 3 and chapter 4 treatment
- withholding rate and federal tax withheld
- recipient and intermediary information when applicable
- state amounts when applicable
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:
{
"_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": "1042s-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:
_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:
- When data is sent: required fields, formats, lengths, and allowed values are checked.
- After a filer or recipient is created: the legal-name/TIN pair begins in
AWAITING_MATCHING. - 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:
https://auth.dev.nutshelllabs.tech/realms/taxclient-demo/protocol/openid-connect/token
Set the client ID and the secret Nutshell provided:
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:
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:
--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:
export NUTSHELL_BASE_URL="https://taxapi.iris.demo.taxclient.nutshelllabs.tech"
export TAX_YEAR="2026"
2. Create the filer
Acme creates one filer resource. The withholding_agent object records its chapter 3 and chapter 4 status.
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": "123 Main St",
"city": "Austin",
"state": "TX",
"zip_code": "78701"
},
"phone_number": "5125550100",
"withholding_agent": {
"chapter_3_status": "CORPORATION",
"chapter_4_status": "US_WITHHOLDING_AGENT_OTHER"
}
}'
This guide uses a readable filer ID supplied by Acme:
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 person who will receive the statement and whose payment is reported to the IRS.
Jennifer provided the applicable foreign tax documentation. Acme maps the name, address, country, chapter status, and foreign TIN information into the recipient record:
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": "customer-8827",
"name": {
"type": "PERSON",
"first_name": "Jennifer",
"last_name": "McNally"
},
"mailing_address": {
"type": "FOREIGN",
"line1": "10 Rue Rivoli",
"city": "Paris",
"country": {
"representation": "ISO_3166_1_ALPHA2",
"identifier": "FR"
},
"postal_code": "75001"
},
"foreign_status": {
"country": {
"representation": "ISO_3166_1_ALPHA2",
"identifier": "FR"
},
"chapter_3_status": "INDIVIDUAL",
"chapter_4_status": "INDIVIDUAL",
"foreign_tin": "FR123456789"
},
"_client": {
"filer_id": "acme-holdings",
"batch_id": "2026-year-end"
}
}'
export RECIPIENT_ID="customer-8827"
What Nutshell validates now
Nutshell immediately checks whether the data has the correct shape. Legal name and mailing address are required, foreign recipients require the applicable country and status information, 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
The foreign TIN comes from the recipient's foreign tax documentation. It is not a U.S. TIN and does not use IRS name/TIN matching. Some situations also require a U.S. TIN. Use the applicable recipient documentation and schema fields when constructing the record.
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 Form1042SBody in the OpenAPI document.
Example: Form 1042-S
Acme creates a Form 1042-S record with illustrative values.
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": "1042s-2026-000417",
"tax_year": 2026,
"data": {
"type": "1042-S",
"unique_form_identifier": "0000000417",
"income_code": "OTHER_ROYALTIES",
"gross_income": "10000",
"chapter": "CHAPTER_3",
"chapter_3": {
"exemption_code": "WITHHELD_NOT_EXEMPT",
"tax_rate": "0.3000"
},
"chapter_4": {
"exemption_code": "PAYEE_NOT_SUBJECT_TO_CHAPTER4_WITHHOLDING",
"tax_rate": "0.0000"
},
"federal_tax_withheld": "3000",
"account_number": "ROYALTY-8827"
},
"_client": {
"source_record_id": "royalty-417"
}
}'
export FORM_ID="1042s-2026-000417"
Form 1042-S amounts are whole-dollar strings. Tax rates are decimal strings. Keep unique_form_identifier stable if the form is later amended.
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.
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.
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 Jennifer's form:
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:
{
"id": "1042s-2026-000417",
"federal_filing_status": "AWAITING_FILING",
"state_filings": [],
"problems": []
}
federal_filing_statusshows whether the federal return is ready.AWAITING_FILINGmeans it passed preparation.AWAITING_CORRECTIONmeans it must be corrected.state_filingscontains a separate status for every required state filing. Review each one because a federal return and its state returns can have different results.problemscontains the errors and warnings found for the form. AnERRORblocks the filing named by the problem. AWARNINGdoes not block filing, but it still requires review.
To inspect every form belonging to Jennifer, list the collection instead:
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. | |
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 Jennifer's statements:
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:
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.
PUBLISHEDmeans the statement went to the recipient.
Publishing acts on all eligible statements in the latest prepared snapshot for the tax year:
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:
- Confirm the Form 1042-S recipient-statement deadline 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.
Notification of statement availability
After Acme publishes Jennifer'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 Jennifer 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.
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:
FILEDmeans the filing was submittedAWAITING_CORRECTIONmeans preparation or an authority returned an errorproblemscontains 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) 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
historyarray of earlier generations, newest first. A form's current version and history retain the filing statuses andproblemsfor each generation. A historicalFILEDstatus shows that generation was submitted. - The statements collection shows which statements were created. A statement with
status: "PUBLISHED"andpublished_atwas delivered to the recipient. - A single statement lists
forms, and each entry includes the formidandgenerationused to build that statement. Match that generation to the form's current version orhistoryto 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 Jennifer's recipient information. Jennifer is still the same recipient, so the integration updates customer-8827 rather than creating a new record.
First, retrieve the complete recipient:
curl --include \
"$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/customer-8827" \
--header "Authorization: Bearer $NUTSHELL_TOKEN"
Use the response as the starting point, then send the complete recipient with the correction:
curl --request PUT \
"$NUTSHELL_BASE_URL/api/v2/$TAX_YEAR/filers/$FILER_ID/recipients/customer-8827" \
--header "Authorization: Bearer $NUTSHELL_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"id": "customer-8827",
"foreign_status": {
"country": {
"representation": "ISO_3166_1_ALPHA2",
"identifier": "FR"
},
"chapter_3_status": "INDIVIDUAL",
"chapter_4_status": "INDIVIDUAL",
"foreign_tin": "REPLACE_WITH_CORRECT_FOREIGN_TIN"
},
"name": {
"type": "PERSON",
"first_name": "Jennifer",
"last_name": "McNally"
},
"mailing_address": {
"type": "FOREIGN",
"line1": "10 Rue Rivoli",
"city": "Paris",
"country": {
"representation": "ISO_3166_1_ALPHA2",
"identifier": "FR"
},
"postal_code": "75001"
},
"_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 customer-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:
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.