Introduction
The OECD's CARFxml schema (currently v1.5) is the canonical data format every CARF and DAC8 reporting CASP must produce. It looks intimidating at first, namespaces, complex types, multiple levels of aggregation, but the structure is rational once you map it against the underlying policy.
This guide walks through the schema from the root element down, with concrete XML snippets. The full XSD is published by the OECD and downloadable from their CARF page. Code samples here use a simplified namespace prefix for readability.
Root structure
A CARF message is a single CARF_OECD root element with three children: a MessageSpec describing the message itself, one or more CarfBody/ReportingGroup blocks containing the actual data, and an envelope version attribute.
<?xml version="1.0" encoding="UTF-8"?>
<crf:CARF_OECD version="1.5"
xmlns:crf="urn:oecd:ties:carf:v1"
xmlns:stf="urn:oecd:ties:stf:v5">
<crf:MessageSpec>...</crf:MessageSpec>
<crf:CarfBody>
<crf:ReportingGroup>
...
</crf:ReportingGroup>
</crf:CarfBody>
</crf:CARF_OECD>MessageSpec
The MessageSpec identifies the message itself: who is sending, to whom, for which reporting period, and whether this is a new submission, a correction, or a void. Three fields drive almost all the behaviour:
MessageRefID, a globally unique identifier for this submission. Convention is<country>-<reporting-entity-id>-<sequence>. Once used, it cannot be reused.MessageTypeIndic, one ofCARF701(new data)CARF702(corrected data) orCARF703(void). Picking the wrong one is the most common cause of rejection.ReportingPeriod, the calendar year asYYYY-12-31.
<crf:MessageSpec>
<crf:SendingCompanyIN>GB1234567</crf:SendingCompanyIN>
<crf:TransmittingCountry>GB</crf:TransmittingCountry>
<crf:ReceivingCountry>FR</crf:ReceivingCountry>
<crf:MessageType>CARF</crf:MessageType>
<crf:Warning>Test submission - do not process</crf:Warning>
<crf:MessageRefID>GB-12345-2026-001</crf:MessageRefID>
<crf:MessageTypeIndic>CARF701</crf:MessageTypeIndic>
<crf:ReportingPeriod>2026-12-31</crf:ReportingPeriod>
<crf:Timestamp>2027-05-15T09:00:00Z</crf:Timestamp>
</crf:MessageSpec>ReportingGroup and AccountReport
Inside CarfBody/ReportingGroup sits the reporting entity (the CASP) and an array of CryptoAsset reports, one per Reportable Person per reportable crypto-asset. A user holding three different reportable tokens produces three CryptoAsset nodes for that user.
<crf:ReportingGroup>
<crf:ReportingEntity>
<crf:Entity>
<crf:ResCountryCode>GB</crf:ResCountryCode>
<crf:TIN issuedBy="GB">UK-12345678</crf:TIN>
<crf:Name>AssetNode Exchange Ltd</crf:Name>
<crf:Address>...</crf:Address>
</crf:Entity>
</crf:ReportingEntity>
<crf:CryptoAsset>
<crf:DocSpec>
<stf:DocTypeIndic>OECD1</stf:DocTypeIndic>
<stf:DocRefId>GB-12345-2026-001-A0001</stf:DocRefId>
</crf:DocSpec>
<crf:Identifier>
<crf:DTI>BTC</crf:DTI>
<crf:Name>Bitcoin</crf:Name>
</crf:Identifier>
<crf:User>...</crf:User>
<crf:AggregatedAmounts>...</crf:AggregatedAmounts>
</crf:CryptoAsset>
</crf:ReportingGroup>MessageRefID, DocRefID must be globally unique and never reused. When you correct a previously filed record, the new record references the original via CorrDocRefId. Misalignment between original and corrected DocRefIDs is the source of most correction-cycle rejections.Transaction aggregates
CARF reports aggregated transaction figures, not individual transactions. Per user, per crypto-asset, per reporting year, you report the number of transactions, the gross amount paid in, the gross amount paid out, and the fair-market value for each of the CARF transfer type categories (CARF501 to 509 for exchange transfers, CARF601 to 606 for retail payment transactions, etc).
<crf:AggregatedAmounts>
<crf:TransferType code="CARF501">
<crf:NumberOfTransactions>147</crf:NumberOfTransactions>
<crf:GrossAmount currCode="EUR">128450.00</crf:GrossAmount>
<crf:NumberOfUnits>2.847</crf:NumberOfUnits>
</crf:TransferType>
<crf:TransferType code="CARF502">
<crf:NumberOfTransactions>89</crf:NumberOfTransactions>
<crf:GrossAmount currCode="EUR">102117.50</crf:GrossAmount>
<crf:NumberOfUnits>2.213</crf:NumberOfUnits>
</crf:TransferType>
</crf:AggregatedAmounts>Note the absence of timestamps on individual transactions, aggregation is the entire point. Sub-aggregation by retail-payment-transaction status applies separately when the $50,000 retail payment threshold is exceeded for a given counterparty (CARF Section II.A.2(c)).
XSD validation and common mistakes
Validate every generated file against the official XSD before submission. The cheapest mistakes to catch at this stage:
- Wrong namespace prefix. The
stf:namespace (Standard Transmission Format) is shared with CRS, copying a CRS template wholesale picks up the wrong version (stf v4 instead of v5). - Empty optional containers. An
<crf:Address/>element with no children fails validation; either populate it fully or omit it. - TIN format violations. Each
TINneeds the issuing country code as an attribute, and the value must match that country's format pattern. - MessageRefID collision. The receiving tax authority rejects duplicate
MessageRefIDs across all time. Use a sequence counter, not a timestamp alone, to guarantee uniqueness. - Mixed reporting periods. One
CarfBodycan only contain data for the singleReportingPerioddeclared inMessageSpec.
Further reading
- OECD, CARFxml User Guide v1.5
- OECD, CARF FAQs (December 2025), corrections and void filings
Get the monthly CARF Alliance briefing
One concise email a month. No spam.