Skip to main content

The CARF XML schema, section by section

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

The CARF XML schema, section by section

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.

The message header (MessageSpec)

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 MessageRefId uniquely identifies the file. Reuse one across submissions and the whole message bounces, since the authority can't tell a real resubmission from a duplicate.
  • The MessageTypeIndic declares what the file is, new data or a set of corrections. The body has to match that declaration. Say "new" but ship corrected records and the file fails, even when every figure is right.
  • A timestamp and the reporting period finish the header. That period has to line up with the jurisdiction's reporting year, and it isn't always a calendar year.

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.

The reporting CASP block (ReportingCASP)

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.

The user record

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 transaction data

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:

  • Acquisitions of crypto against fiat currency;
  • Disposals of crypto for fiat currency;
  • Exchanges of one crypto-asset for another;
  • Transfers, including moves to wallets outside the reporting system and certain reportable retail payment transfers above the set value.

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.

Identifiers and corrections (DocSpec)

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.

National variations on the baseline

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.

From schema to filed report

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.

About the author
Sukesh Tedla
Founder & CEO
FAQs

What format is a CARF report?

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.

What are the main CARF transaction categories?

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.

Why is MessageRefId or DocRefId so important?

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.

Is a CARF file the same everywhere?

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.

Related articles

Ready when you are

File your crypto taxes in minutes.

Generate an audit-ready report aligned to your jurisdiction. No credit card required.

See pricing