Technical·14 min read

CARF XML Schema Explained, A Developer's Guide to CARFxml_v1.5.xsd

How the OECD's CARFxml schema is structured, what each top-level element means, and the validation pitfalls that bite developers building CARF generators for the first time.

CARF Alliance editorial

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.

XMLCARFxml_v1.5_skeleton.xml
<?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 of CARF701 (new data) CARF702 (corrected data) or CARF703 (void). Picking the wrong one is the most common cause of rejection.
  • ReportingPeriod, the calendar year as YYYY-12-31.
XMLMessageSpec.xml
<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.

XMLReportingGroup.xml
<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>
DocRefID convention
Like 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).

XMLAggregatedAmounts.xml
<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:

  1. 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).
  2. Empty optional containers. An <crf:Address/> element with no children fails validation; either populate it fully or omit it.
  3. TIN format violations. Each TIN needs the issuing country code as an attribute, and the value must match that country's format pattern.
  4. MessageRefID collision. The receiving tax authority rejects duplicate MessageRefIDs across all time. Use a sequence counter, not a timestamp alone, to guarantee uniqueness.
  5. Mixed reporting periods. One CarfBody can only contain data for the single ReportingPeriod declared in MessageSpec.
Engineering tip
Treat XSD validation as a hard gate in the deployment pipeline. The XSD is small, the validator is fast, and "rejected by tax authority" is a much more expensive failure mode than "rejected by CI."

Further reading

  • OECD, CARFxml User Guide v1.5
  • OECD, CARF FAQs (December 2025), corrections and void filings
Tags
XMLSchemaDeveloperValidation

Get the monthly CARF Alliance briefing

One concise email a month. No spam.

Monthly bulletin. No spam. Unsubscribe anytime.