Preflight

Engineering · 2026-07-09

Most teams can’t open the file that prints their statements

AFP/MO:DCA runs a huge share of the world’s transactional mail and is nearly toolless outside enterprise software. Here’s how we parse it entirely in the browser — and what an honest parser refuses to guess.

AFP — Advanced Function Presentation — predates the web. It came out of IBM in the 1980s, moves to production printers over IPDS, and still composes a huge share of the world’s bank statements, insurance documents, and healthcare EOBs. If you work anywhere near transactional print, AFP files flow through your systems daily.

And yet: ask a team to answer “is this AFP batch structurally sane?” and watch what happens. The tooling that can even open the format is enterprise software — licensed per seat, installed somewhere specific, owned by another department. The formats documentation (MO:DCA — Mixed Object Document Content Architecture) is public via the AFP Consortium, but public and approachable are different things. Most vendors in this space sell conversion — AFP in, PDF out. Almost nobody just tells you whether the file is well-formed.

The format is friendlier than its reputation

An AFP file is a flat sequence of structured fields. Every field starts with a 0x5A carriage-control byte, then a two-byte big-endian length, a three-byte identifier (SFID), a flag byte, two reserved bytes, and payload. That’s the whole framing story. No cross references to resolve, no compression dictionary to bootstrap — you can walk an AFP file with a while loop.

Structure comes from Begin/End pairs. BDT…EDT wraps the document; BPG…EPG wraps each page; groups, presentation-text objects, and overlays nest inside in last-opened-first-closed order. Names inside the fields are EBCDIC — code page 500, another small museum piece — and resource references (fonts via MCF, overlays via IPO, page segments via IPS) are eight-character EBCDIC names pointing at objects that live outside the file, in a resource library on the production system.

What a structural validator can honestly check

Our free validator does four things, all derivable from the bytes alone: it verifies framing (every field opens with 0x5A, declares an in-bounds length, and the stream ends exactly at a field boundary — truncation is the classic transfer failure, and FTP in ASCII mode has ruined more AFP files than any parser bug); it checks Begin/End nesting with a plain stack; it confirms exactly one document envelope with pages nested inside; and it builds an inventory — every structured field with its name, byte offset, and length, plus the page count and every referenced resource name.

Just as important is what it refuses to do. An SFID we don’t recognize is reported as unknown — counted, located, and flagged as a warning — not guessed at. Whether a referenced font or overlay actually exists in your resource library is not knowable from the file, so we say exactly that instead of implying it was verified. The free tool names the common IS/3 subset and is honest about the rest. (Resource resolution, rendering, and deep semantic validation run in the paid product, server-side, where that work is actually possible.)

Why client-side was the whole point

AFP files are statements and EOBs — they carry names, addresses, account numbers, health information. The reason “just upload it to a converter site” never became the norm in this industry is that nobody responsible for that data should be uploading it anywhere casually. So the validator runs entirely in your browser: the parser is compiled into the page, the file is read locally, and there is no upload endpoint behind it. Parsing a structured-field stream is cheap — a multi-hundred-page statement run inventories in milliseconds on a laptop — and the file never touches a network.

Try it: the free AFP validator (there’s a 20-second demo on the page), or start with what is AFP? if the format is new to you. If your team fights AFP regularly, the paid modules add the parts that need a server — resource resolution, rendering and regression diff, USPS checks on the composed output, batch and CI processing.