Form 1099

IRIS XML vs FIRE Flat File: A Developer’s Migration Guide

If you’re the developer who’s been handed the FIRE-to-IRIS migration, this guide is for you. Not the executive summary. Not the compliance overview. This is the technical breakdown – data formats, authentication, API structure, XML schema details, and the architectural decisions you need to make bef

By

If you’re the developer who’s been handed the FIRE-to-IRIS migration, this guide is for you. Not the executive summary. Not the compliance overview. This is the technical breakdown – data formats, authentication, API structure, XML schema details, and the architectural decisions you need to make before writing a single line of code.

The IRS stops accepting FIRE filings on November 19, 2026 at 3 p.m. ET. Everything that currently goes through FIRE’s flat-file upload must go through IRIS’s XML-based API instead. Here’s what that actually means at the code level.

FIRE: Pub 1220 T2023123456789COMPANY NAME… A2023123456789JOHN DOE … B2023123456789JOHN DOE … C2023000000015000 … F2023000000000001 … IRIS: XML Schema <Form1099NEC> <PayerTIN>123456789</PayerTIN> <PayeeName>JOHN DOE</PayeeName> <NEC1>1500.00</NEC1> </Form1099NEC> Field Mapping 750 chars/record Self-describing elements

FIRE Flat Files: What You’re Migrating From

If you’ve worked with FIRE, you know the format intimately. IRS Publication 1220 defines a fixed-width text file with record types identified by the first character of each line. The structure is hierarchical but encoded positionally:

// FIRE File Structure (Publication 1220)
Trecord  - Transmitter record (1 per file)
Arecord  - Payer record (1 per payer)
Brecord  - Payee record (1 per recipient)
Crecord  - End of payer (totals)
Frecord  - End of transmission (totals)

// Example B Record (1099-NEC, positions shown)
B20260    999887766SMITH               JANE                0000015000000
││   │     │        │                                   │
││   │     │        │                                   └─ Amount: $150,000.00
││   │     │        └─ Name (40 chars, left-justified)
││   │     └─ Payee TIN (9 digits, no dashes)
││   └─ Corrected return indicator
│└─ Tax year
└─ Record type

Key characteristics of the FIRE format that affect your migration:

  • Fixed-width fields. Every field occupies specific character positions. No delimiters, no tags. Position 1 = record type, positions 2-5 = tax year, and so on for 750+ characters per B record.
  • Right-justified numerics, left-justified alphas. Amounts are right-justified, zero-padded, no decimal points. Names are left-justified, space-padded.
  • Implicit structure. The hierarchy (transmitter → payer → payees) is implied by record order, not encoded in the format.
  • Single file per transmission. One file, one upload, synchronous acknowledgment.

IRIS XML: What You’re Migrating To

IRIS uses structured XML based on IRS-defined schemas. The format is self-describing, hierarchical, and validated against an XSD. Here’s what the equivalent 1099-NEC looks like in IRIS XML:

<?xml version="1.0" encoding="UTF-8"?>
<Form1099NEC xmlns="urn:us:gov:treasury:irs:ir">
  <SubmissionId>550e8400-e29b-41d4-a716-446655440000</SubmissionId>
  <TaxYear>2026</TaxYear>

  <Payer>
    <PayerTIN>123456789</PayerTIN>
    <PayerName>
      <BusinessName>ACME CORPORATION</BusinessName>
    </PayerName>
    <PayerAddress>
      <AddressLine1>100 MAIN STREET</AddressLine1>
      <City>ANYTOWN</City>
      <State>NY</State>
      <ZipCode>10001</ZipCode>
    </PayerAddress>
  </Payer>

  <Payee>
    <PayeeTIN>999887766</PayeeTIN>
    <PayeeName>
      <FirstName>JANE</FirstName>
      <LastName>SMITH</LastName>
    </PayeeName>
    <PayeeAddress>
      <AddressLine1>456 OAK AVENUE</AddressLine1>
      <City>SOMEWHERE</City>
      <State>CA</State>
      <ZipCode>90210</ZipCode>
    </PayeeAddress>
    <NonemployeeCompensation>150000.00</NonemployeeCompensation>
  </Payee>
</Form1099NEC>

The differences are structural, not cosmetic. Your entire data pipeline needs to change.

Field Mapping: FIRE Positions to IRIS XML Elements

The core of any migration is the field map. Here’s a representative mapping for 1099-NEC (other form types follow the same pattern with form-specific fields):

FIRE Field Position IRIS XML Element Notes
Record Type 1 Implicit (element hierarchy) No equivalent – structure defines record type
Tax Year 2-5 <TaxYear> Same format (4-digit year)
Payer TIN 12-20 <PayerTIN> 9 digits, no dashes in both
Payee TIN 12-20 (B rec) <PayeeTIN> 9 digits, no dashes in both
Payee Name Various (40 chars) <FirstName>, <LastName> Breaking change: FIRE uses combined name; IRIS requires split
Payment Amount 55-66 <NonemployeeCompensation> Breaking change: FIRE = cents (no decimal); IRIS = dollars.cents
Address Various <AddressLine1>, <City>, etc. Breaking change: FIRE concatenates; IRIS requires structured fields
Watch for breaking changes: The three fields marked above (name splitting, amount formatting, and address structuring) cause the most migration bugs. FIRE’s combined name field "SMITH JANE" needs to be parsed into <FirstName>JANE</FirstName> and <LastName>SMITH</LastName>. Edge cases like suffixes (“SMITH JR JOHN”), business names, and DBAs make this non-trivial. For the full schema reference, see the IRIS XML format guide.

Authentication: From TCC + Password to OAuth 2.0

FIRE authentication was straightforward: TCC, username, password. Upload via the FIRE web portal or through the bulk filing process. No tokens, no refresh cycles, no scopes.

IRIS uses OAuth 2.0. Here’s what your authentication flow needs to handle:

// Step 1: Request access token
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={your_client_id}
&client_secret={your_client_secret}
&scope=iris.submit

// Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "iris.submit"
}

// Step 2: Use token in submission requests
POST /iris/api/v1/submissions
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/xml

<!-- Your IRIS XML payload -->

Implementation considerations for OAuth 2.0 with IRIS:

  • Token expiration. Access tokens expire (typically 1 hour). Your submission pipeline needs automatic token refresh – especially for high-volume batch jobs that run longer than the token lifetime.
  • Credential storage. Client secrets must be stored securely. If your FIRE credentials lived in a config file, your IRIS credentials need a secrets manager or environment variables at minimum.
  • Error handling for auth failures. Token expired mid-batch? 401 response? Your code needs to re-authenticate and retry the failed request without resubmitting records that already succeeded.
  • Sandbox vs production credentials. You’ll have separate client IDs for the test environment and production. Make sure your deployment pipeline doesn’t cross them.

For the complete authentication implementation guide, see the IRIS API integration guide.

API Architecture: Synchronous to Asynchronous

This is the architectural change that catches developers off guard. FIRE was synchronous: upload file, get acknowledgment, done. IRIS is asynchronous: submit XML, receive a submission ID, poll for status.

// Step 1: Submit returns
POST /iris/api/v1/submissions
→ 202 Accepted
{
  "submissionId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PROCESSING",
  "recordCount": 5000,
  "submittedAt": "2027-01-15T14:30:00Z"
}

// Step 2: Poll for status (with exponential backoff)
GET /iris/api/v1/submissions/550e8400-e29b-41d4-a716-446655440000/status
→ 200 OK
{
  "submissionId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "COMPLETED",
  "accepted": 4987,
  "rejected": 13,
  "errors": [
    {
      "recordIndex": 42,
      "field": "PayeeTIN",
      "code": "INVALID_TIN",
      "message": "TIN fails validation check"
    }
    // ... more errors
  ]
}

// Step 3: Resubmit corrected records
POST /iris/api/v1/submissions
→ 202 Accepted (for corrected batch)

This async pattern requires new infrastructure in your filing pipeline:

  • Submission tracking. You need a persistent store (database table, at minimum) mapping submission IDs to your internal filing batch IDs. You can’t just fire-and-forget.
  • Polling with backoff. Implement exponential backoff when polling for status. Don’t hammer the status endpoint every second – you’ll hit rate limits.
  • Partial failure handling. A batch of 5,000 might have 4,987 accepted and 13 rejected. Your system needs to extract the rejected records, fix the issues, and resubmit only those records – not the entire batch.
  • Idempotency. If your polling request times out, you need to retry without accidentally creating a duplicate submission. Track submission IDs server-side.
Sync
FIRE: Upload → ACK → Done
Async
IRIS: Submit → Poll → Handle
3x
More Error Handling Code

XML Schema Validation: Your New Best Friend

One advantage of moving to XML: you can validate locally before submitting. The IRS publishes XSD schemas for each form type. Use them.

// C# - Validate XML against IRS schema before submission
var schemas = new XmlSchemaSet();
schemas.Add("urn:us:gov:treasury:irs:ir",
    "IRS-Form1099NEC-Schema.xsd");

var settings = new XmlReaderSettings
{
    ValidationType = ValidationType.Schema,
    Schemas = schemas
};

settings.ValidationEventHandler += (sender, e) =>
{
    // Log validation errors BEFORE submitting
    logger.LogError($"Schema error at line {e.Exception.LineNumber}: "
        + $"{e.Message}");
};

using var reader = XmlReader.Create(xmlStream, settings);
while (reader.Read()) { } // Triggers validation
# Python - Validate with lxml
from lxml import etree

schema_doc = etree.parse("IRS-Form1099NEC-Schema.xsd")
schema = etree.XMLSchema(schema_doc)

xml_doc = etree.parse("submission.xml")

if not schema.validate(xml_doc):
    for error in schema.error_log:
        print(f"Line {error.line}: {error.message}")

Validate every XML document before submission. Every error you catch locally is a rejected record you don’t have to resubmit through the IRIS API.

The Build vs Buy Decision Framework

Here’s the honest assessment. Building a direct IRIS integration involves:

  • TCC application and approval (45+ days)
  • XML generation – Mapping your data model to IRS schemas for each form type. Name parsing, amount formatting, address structuring.
  • OAuth 2.0 implementation – Token management, refresh logic, credential rotation.
  • Async submission pipeline – Submit, track, poll, handle partial failures, retry.
  • Error handling – Parse IRIS error responses, categorize (retryable vs data fix), route to appropriate remediation.
  • Corrections workflow – Separate schemas and possibly separate API endpoints for corrected returns.
  • Testing – Sandbox validation with realistic data volumes and edge cases.
  • Ongoing maintenance – Schema updates, API version changes, TCC renewal, security patches.

Realistic development estimate: 400-800 hours for a multi-form-type integration with proper error handling and testing. At $150/hour for a senior developer, that’s $60,000-$120,000 in development cost alone, not counting ongoing maintenance.

The alternative: A filing provider handles all of this. BoomTax accepts data via API, CSV upload, or even your existing FIRE-format flat files. The provider handles XML generation, schema validation, OAuth, submission, status tracking, error handling, and corrections. Your integration point is a single API call or file upload – not a ground-up IRIS implementation.

Common Migration Pitfalls (From a Developer’s Perspective)

Pitfall 1: Name Parsing

FIRE encodes names in a single field: "SMITH JANE" or "SMITH JR JOHN A". IRIS requires separate <FirstName>, <MiddleName>, <LastName>, and <Suffix> elements. Parsing a combined name field into components is deceptively complex. “VAN DER BERG ANNA” – where does the last name end? “O’BRIEN-SMITH MARY JO” – is “JO” a middle name or part of the first name?

If your source data already has separate name fields (most databases do), use them directly instead of parsing the FIRE combined format. If your only source is the FIRE file itself, invest in a robust name parser and validate the output manually for edge cases.

Pitfall 2: Amount Formatting

FIRE amounts are integer cents in a right-justified, zero-padded field: 0000015000000 means $150,000.00. IRIS amounts are decimal dollars: 150000.00. The conversion is simple math, but the bugs come from:

  • Integer overflow in languages that don’t handle large numbers natively
  • Floating-point precision errors when dividing by 100
  • Rounding inconsistencies between your calculation and the IRS’s validation

Use decimal types (C# decimal, Python Decimal, Java BigDecimal), not floating-point, for all amount conversions.

Pitfall 3: Character Encoding

FIRE files are ASCII. IRIS XML is UTF-8. If your data contains characters outside the ASCII range (accented characters in names, special characters in business names), they need proper UTF-8 encoding in the XML output. Also watch for XML-special characters in data: &, <, >, ", ' all need entity encoding in XML attribute values and text content.

A Practical Migration Architecture

If you’re building the integration, here’s a clean architecture:

┌──────────────────────────────────────────────────────────┐
│  Your System                                             │
│                                                          │
│  ┌─────────────┐    ┌──────────────┐    ┌────────────┐  │
│  │ Data Source  │───▶│ XML Builder  │───▶│ Validator  │  │
│  │ (DB/ERP/     │    │ (per form    │    │ (XSD       │  │
│  │  FIRE file)  │    │  type)       │    │  check)    │  │
│  └─────────────┘    └──────────────┘    └─────┬──────┘  │
│                                                │         │
│                                          ┌─────▼──────┐  │
│  ┌─────────────┐    ┌──────────────┐    │ Submission │  │
│  │ Error       │◀───│ Status       │◀───│ Client    │  │
│  │ Handler     │    │ Tracker      │    │ (OAuth +  │  │
│  │ (retry/fix) │    │ (poll/store) │    │  HTTP)    │  │
│  └─────────────┘    └──────────────┘    └───────────┘  │
└──────────────────────────────────────────────────────────┘
                                                   │
                                              IRIS API

Each component is independently testable. The XML Builder can be validated against schemas without any network calls. The Submission Client can be tested against the IRIS sandbox. The Status Tracker can be tested with mock responses. This modularity is what lets you iterate quickly and catch problems early.

Frequently Asked Questions

Can we keep generating FIRE files and convert them to IRIS XML?

Yes – and this is actually a pragmatic migration strategy. If your existing systems reliably generate FIRE-format files, you can build a converter that reads the flat file and outputs IRIS XML. This isolates the change: your upstream systems stay the same, and only the last mile changes. BoomTax takes this approach one step further – you upload the FIRE file directly and BoomTax handles the entire conversion and IRIS submission. Zero code changes on your end.

What about the BoomTax API for automated filing?

If your system currently generates FIRE files programmatically, BoomTax offers an API that accepts structured data (JSON) and handles the IRIS XML generation, submission, and status tracking. Your integration is a REST API call instead of an IRIS implementation. The API handles authentication, schema validation, batching, and error reporting – the parts that take months to build correctly.

How does the IRIS sandbox differ from production?

The sandbox mirrors production validation rules, schema enforcement, and error response formats. Key differences: sandbox submissions don’t create real IRS filings, sandbox uses separate TCC credentials, and sandbox may have different rate limits. Test against the sandbox with production-realistic data volumes to surface issues that only appear at scale.

What happens to existing FIRE-based integrations for state filing?

State filing requirements vary. Some states use the Combined Federal/State Filing Program (CF/SF), which may transition to IRIS-based submission. Others maintain independent filing portals. Check each state’s requirements individually. The IRS’s move to IRIS doesn’t automatically change state filing formats, but many states are likely to follow the federal lead over time.

Is there a rate limit on IRIS API submissions?

The IRS has not published detailed rate limit specifications. During testing, implement conservative rate limiting (e.g., 1-2 submissions per second) and respect any 429 Too Many Requests or Retry-After headers in responses. Build your batch processor to throttle automatically rather than fail on rate limit errors. High-volume filers should plan for submissions to take hours, not minutes.

The Developer’s Honest Assessment

If you’re a developer evaluating this migration, here’s the straight talk:

Building a direct IRIS integration is a real software project. It’s not a weekend hack. The XML generation is manageable. The OAuth is standard. But the error handling, partial failure recovery, correction workflows, multi-form-type support, and ongoing schema maintenance add up to a significant investment – and all of it has to work perfectly under deadline pressure in January.

If your organization has dedicated development resources, files a single form type, and has started already – build it. You’ll have a clean, custom integration that fits your architecture.

If you’re starting in September with multiple form types, high volume, and a team that has other priorities – use a provider for this filing year and build the integration for 2028 when there’s no deadline pressure. That’s not a compromise. That’s engineering judgment.

For the developer evaluating BoomTax: BoomTax accepts FIRE flat files directly – your existing output works as-is. It also offers a REST API for programmatic filing. No IRIS XML, no OAuth to the IRS, no submission tracking infrastructure. Your team can focus on building the direct integration at a sustainable pace while BoomTax handles the January deadline. See the API integration guide for details.

Create your free BoomTax account and try submitting a test file through the API. Evaluate the integration surface area compared to building IRIS directly. Then make your build-vs-buy recommendation with data, not assumptions.

BoomTax, The Boom Post, and its affiliates do not provide tax, legal or accounting advice. This material has been prepared for informational purposes only, and is not intended to provide, and should not be relied on for, tax, legal or accounting advice. You should consult your own tax, legal and accounting advisors prior to engaging in any transaction.

About Author