A complete walkthrough of the CARF XML report: the message header, the reporting CASP block, each user record, and how transactions are aggregated.

Ask a tax authority what a CARF report is and the answer is narrow: one XML file, built to a fixed schema the OECD publishes. Accept or reject comes down to a single question. Does the file match the schema? So learn the shape before you build against it. This guide reads the file from top to bottom, the header that describes the message, the block that identifies you, one record per reportable user, and the way each user's activity gets grouped. None of it is hard once you can see the structure.
Read the schema as a map of where your data has to come from. Every element traces back to something, either collected at onboarding or reconciled from transactions. And the holes in your data are the same holes that fail validation.
Every CARF file opens with a message specification that frames the submission. It records who's sending the message and to which authority, plus the reporting period it covers. It also carries two things people routinely get wrong: the MessageRefId and the MessageTypeIndic.
The header validates first, so an error here bounces the file before the authority ever reads your data. We give it its own checkpoint in the companion piece on the errors that get filings rejected.
Next is the block that identifies you as the Reporting Crypto-Asset Service Provider: legal name, address, residence country code, and your identification or tax number in the reporting jurisdiction. Small block. But it anchors the file, because every record beneath it reports as coming from this entity. Have nexus in more than one jurisdiction and this is where your choice of reporting jurisdiction surfaces, and it has to be the one your due-diligence and nexus analysis actually landed on.
Most of the file is one record per reportable user. Each record splits in two: who the user is, and what they did.
The identity half carries the user's name, address, one or more residence country codes, date and place of birth for individuals, and a taxpayer identification number for each jurisdiction of residence. Entity accounts add the controlling persons, each with their own identity and residence. This is exactly the payload that the self-certification and TIN validation workflow exists to produce, and a missing or malformed TIN here is one of the single most common reasons a record gets rejected.
The activity half is where teams underestimate the work. CARF doesn't want your raw ledger. It wants each user's reportable activity for the period, sorted into categories and reported as aggregates. Broadly, the schema separates:
Within each category, and for each type of crypto-asset, you report aggregate figures: number of units, the gross amount as a fair market value, and the transaction count. So every value has to be computed on the right cost basis, in the currency the jurisdiction expects, and grouped correctly, all before it reaches the file. The input is a ledger of individual trades. The output is a small set of per-asset, per-category aggregates.
Each document inside the file, the CASP block and every user record, carries its own document specification: a unique DocRefId plus a type indicator for whether it's new, corrected or deleted. Those identifiers are what make later amendments possible, since a correction points back at the exact DocRefId it replaces. Sloppy identifiers break every future fix, so we cover them in full in correcting a CARF filing.
What's described here is the OECD baseline. Individual authorities layer their own national envelopes and fields on top, so a file that's valid CARF at the OECD level can still be rejected by a national system expecting its own format. Those differences, and why they trip up a generic build, are the subject of CARF vs DAC8 XML.
Reading the schema top to bottom is really a checklist of where your data comes from: identity and residence from onboarding, TINs from self-certification, every amount from a reconciled transaction ledger valued on the right basis. Our CARF and DAC8 reporting platform pulls all of it into a valid file, aggregates the transaction categories correctly, and checks it against the schema before you submit, so what you send matches what each authority actually accepts. For where this sits in a venue's stack, see exchanges and custodians, and the OECD exchange-of-information hub publishes the schema and its user guide in full.
A single XML file, built to a schema the OECD publishes. It has a message header (MessageSpec), a block identifying the reporting CASP, and one record per reportable user carrying their identity, tax residence and aggregated transaction data.
Four, broadly: acquisitions of crypto against fiat, disposals for fiat, crypto-to-crypto exchanges, and transfers (including certain reportable retail payments above the threshold). Each one is reported per asset as aggregates, units, gross fair-market value and transaction count.
They're the unique identifiers for the file and for each document in it. Reuse or duplicate one and the file gets rejected. And corrections work by pointing a new record back at the exact DocRefId it replaces, so identifier hygiene matters for both first filings and every later amendment.
No. The OECD baseline schema is shared, but individual jurisdictions add national envelopes and fields on top. A file valid at the OECD level can still be rejected by a national system, so aim at the exact format each authority accepts. The baseline alone won't clear a national gateway.

Brokers face a global layer (CARF/DAC8) and a US domestic layer (1099-DA and backup withholding). Here's how to meet both from one data layer.

Advising a CASP toward CARF and DAC8 readiness? The assessment framework, the common gaps, and how to hand clients a working pipeline, not a slide deck.

Custodial providers are in scope as reporting CASPs. Here's the due-diligence and reporting obligation for a custodian, including the transfer edge cases.
Generate an audit-ready report aligned to your jurisdiction. No credit card required.