Skip to content

Extracting Data From a Schedule K-1

10 min read · updated August 11, 2026

A Schedule K-1 is where a pass-through entity tells one owner what share of its year belongs to them. It is the densest form in this cluster, and the single most expensive mistake is treating the three versions of it as one document.

Three forms, one name, different box numbers

There are three Schedules K-1, attached to three different returns: one for partnerships filing Form 1065, one for S corporations filing Form 1120-S, and one for estates and trusts filing Form 1041. They look alike. Their income boxes are numbered differently.

The clearest instance: on the partnership K-1, box 4 is guaranteed payments to the partner, split across sub-boxes for services and for capital, and interest income appears in a later box. On the S corporation K-1, there are no guaranteed payments — the concept does not exist for an S corporation — and box 4 is interest income. So a schema that maps “K-1 box 4” to a single concept will silently reclassify interest as compensation, or the reverse, on every document of one type.

The same divergence runs through the rest of the grid: the ordinary business income box happens to be box 1 on both, which is exactly enough coincidence to make a developer believe the forms agree, and from there the numbering drifts apart. The IRS publishes each form and its instructions separately — the partnership version is at About Schedule K-1 (Form 1065) — and the instructions are the authority for which box is which on the version in front of you.

Detect the version from the parent form number printed in the header, not from the layout. It is unambiguous, it is in a fixed place, and every downstream mapping depends on it.

Three parts that need three sub-schemas

The form divides into three parts with genuinely different shapes, which is why flattening it into one dictionary of values loses information you need.

  • Part I — the entity. A handful of identifiers: the entity’s taxpayer identification number, its name and address, the IRS centre where the return was filed, and a checkbox for a publicly traded partnership. Small, stable, and the part that joins this document to every other K-1 from the same entity.
  • Part II — the owner. Mixed in type and the most under-extracted part of the form. It carries the owner’s identification, checkboxes distinguishing a general from a limited partner and a domestic from a foreign one, the type of entity the owner is, percentage shares of profit, loss and capital given as beginning and ending pairs, the owner’s share of liabilities split by category, and a capital account analysis. That analysis is a roll-forward: beginning capital, plus contributions, plus the share of income, minus withdrawals and distributions, equals ending capital. It is the only arithmetic on the form and it is checkable.
  • Part III — the share of the year. The long grid of income, deduction, credit and other items. Mostly amounts, but several boxes carry a letter code beside each amount, and those boxes can hold more than one code.

Modelling all three as a flat map produces a record that cannot express the roll-forward, cannot express a beginning-and-ending pair, and cannot hold two codes in one box. Each part gets its own shape.

Codes, and the statement they point to

Several Part III boxes — other income, other deductions, credits, and the general “other information” box — are not single values. They are lists of code-and-amount pairs, where the code letter selects which of dozens of specific items the amount represents. A single box can legitimately contain four or five entries.

The printed form does not have room. So when there are more entries than printed lines, the box contains the word STMT or a reference to an attached statement, and the actual values live on additional pages behind the form — pages with no fixed layout at all, sometimes a neat table of codes and amounts, sometimes a paragraph of prose, sometimes several statements for several boxes concatenated.

This is the central extraction problem of the K-1 and it is the one a generic document pipeline gets wrong. An extractor that reads the form face and stops returns a complete-looking record whose most important fields say “see statement”, and nothing downstream knows that the number is missing rather than zero. The information reporting the owner’s qualified business income deduction, for instance, is conventionally delivered this way: a code in a box on the face, and the per-business detail on a statement.

Practical handling: detect the statement pointer explicitly as a value type of its own, distinct from an amount and from a blank. Then the record can say “this box has a code and its amount is on a statement”, and a completeness check can refuse to finalise the document until the statement pages are located and parsed. The pointer is a fact worth extracting even when you cannot follow it.

The checkbox that says the data is elsewhere

There is a checkbox on the K-1 indicating that a Schedule K-3 is attached. Foreign transaction detail that used to appear on the K-1 moved onto the separate Schedules K-2 and K-3, which run to many pages of their own, and the checkbox is the K-1’s way of saying so.

Treat it as a completeness signal, because that is exactly what it is: if the box is ticked and your document set contains no K-3, you can state with certainty that the package is incomplete, before anybody tries to use the numbers. That is a rare and valuable thing in document extraction — a field on the document that tells you whether you have all of the document.

A schema that can represent all of it

{
  "form": "1065",                      # or "1120S" / "1041"
  "tax_year": 2025,
  "final_k1": false, "amended_k1": false,
  "entity":  { "tin": "XX-XXXXXXX", "name": "...", "ptp": false },
  "owner":   {
    "tin": "XXX-XX-XXXX",
    "partner_type": "limited",
    "profit_share":  { "beginning": 0.05, "ending": 0.05 },
    "capital_account": {
      "beginning": 120000, "contributed": 0,
      "current_year_net": 18400, "withdrawals": -12000,
      "ending": 126400
    }
  },
  "part_iii": [
    { "box": "1",  "code": null, "amount": 18400 },
    { "box": "20", "code": "Z",  "amount": null,
      "value_type": "see_statement", "statement_ref": "Statement A" }
  ],
  "k3_attached": true,
  "statements_parsed": false
}

Three things that schema does which a flat one cannot. It represents a box with a code, so the same box can appear more than once. It represents “the value is on a statement” as a value type rather than as a null, so absence and elsewhere are distinguishable. And it carries the roll-forward as a structure you can assert on: beginning plus contributions plus current-year net plus withdrawals should equal ending, and a failure there is the same kind of localised diagnostic as a statement that does not balance in the bank balance page.

Two flags at the top of the form belong in the record for the same reason the corrected box does on a 1099: a final K-1 and an amended K-1 each change how the document should be consumed, and both are easy marks to miss beside a dense grid.