OECD DPI XML Schema and User Guide
Approved 17 March 2022. Sets the elements, the code lists and the requirement levels this checker reads.
Check a seller export against the OECD DPI XML Schema in your browser, then take away a chase list naming every seller, field and fix. Nothing is uploaded.
What the checks are based on
Findings come from the DPI XML Schema v1.0 and from the OECD User Guide that documents it, and each one carries the page or the element it came from so you can check the reasoning against the source rather than take it on trust. Gruv holds no tax licence and files nothing on your behalf.
Approved 17 March 2022. Sets the elements, the code lists and the requirement levels this checker reads.
DAC7. Where the guide marks an element EU Specific, the requirement comes from here, and the checker labels the finding the same way.
Schema and code lists transcribed from OECD Model Rules for Reporting by Digital Platform Operators XML Schema: User Guide for Tax Administrations, checked 1 September 2026. Member States publish their own variants of the schema, so validate any draft against the XSD of the route you file through.
Loading the checker…
Every check here comes from one of two places. The first is the DPI XML Schema v1.0 itself, which enumerates 252 country codes, 186 currency codes and 27 Member State codes, and types a monetary amount as a whole number. A value outside those lists is rejected by any validating parser, so the checker calls it blocking. The second is the OECD User Guide, which sets requirement levels and page by page says which elements must be present. A missing business registration number loads fine and still breaches DAC7, so the checker calls that required rather than blocking, and cites the page.
Take a file of 4,000 rows where 900 individual sellers have no TIN. The blocking count is zero for those rows if each one is flagged unknown, because the guide accepts NOTIN with the unknown attribute set. What the checker returns instead is 900 required findings against place of birth, because DAC7 asks for the city and country of birth exactly where no TIN is available. That distinction decides your next four weeks: chasing 900 tax numbers is a different project from filling in 900 birth places you may already hold in the sign-up record.
What it will not do matters as much. It does not check a TIN against a Member State format, because those formats are set by each filing Member State rather than by the schema, and a confident false failure on correct data would be worse than no check. It does not decide whether a seller is in scope, which is a due diligence question about the seller. The XML it writes is a draft: several Member States publish their own variant of the schema, so validate it against the XSD of the route you file through before you submit anything.
Checked 1 September 2026. Tool pages carry figures that change, so confirm anything you rely on against the authority that publishes it.
Drop or paste a CSV. It is read in the browser and never sent anywhere.
Findings grouped by cause, split into blocking, required and worth checking.
One CSV line per gap, naming the seller reference, the field and what to ask for.
Add the filer details, then validate the draft where you file.
Size the gap in a seller book before the January filing date arrives.
Turn a schema failure into a list of sellers to contact, with the reason attached.
See which columns your export is missing before writing the XML mapping.
Understand your own data quality before a filing vendor quotes on it.
Most DAC7 gaps start where seller onboarding stopped asking. Gruv keeps tax and payout details on one seller record, with form readiness gated and exportable for filing partners. Talk to the team about what your data looks like.
Many teams start with a narrow launch in weeks.
Drop a CSV, or paste one. The file is read in this browser and checked here. Nothing is uploaded, so the personal data in a seller export never reaches Gruv or anyone else. Closing the tab clears it.
Drop a CSV file here
One row per seller and activity. For rented property, one row per listing.
Headers are matched without regard to case, spaces or punctuation, and common source-system names are recognised, so an export headed Account ID or ResCountryCode lands on the right field. Columns the checker does not read are listed back to you rather than dropped in silence.
| Column | DPI element | Notes |
|---|---|---|
| seller_id | Not reported | Your own reference for the seller. Not reported. Rows sharing a seller_id are treated as one Reportable Seller. |
| seller_type | Identity/EntitySeller | Identity/IndividualSeller | individual or entity. Decides which set of identity rules applies. |
| res_country_code | ResCountryCode | Jurisdiction of tax residence, ISO 3166-1 alpha-2. Repeatable: separate several with a semicolon. |
| tin | TIN | Tax identification number. Leave blank and set tin_unknown to true where the seller has none. |
| tin_issued_by | TIN@issuedBy | Jurisdiction that issued the TIN, ISO 3166-1 alpha-2. |
| tin_unknown | TIN@unknown | true where no TIN exists or is known. The draft then files NOTIN with unknown="true". |
| vat | VAT | VAT identification number where the platform holds one. |
| first_name | Name/FirstName | Individual sellers. An initial, or NFN where no first name was provided, is accepted by the schema. |
| last_name | Name/LastName | Individual sellers. |
| birth_date | BirthInfo/BirthDate | Individual sellers, yyyy-MM-dd. |
| birth_city | BirthInfo/BirthPlace/City | Required under DAC7 where no TIN is available. |
| birth_country | BirthInfo/BirthPlace/CountryInfo/CountryCode | Required under DAC7 where no TIN is available, ISO 3166-1 alpha-2. |
| birth_former_country | BirthInfo/BirthPlace/CountryInfo/FormerCountryName | For a seller born in a jurisdiction that has since ceased to exist, such as Czechoslovakia. Fill this in instead of birth_country, not as well. |
| legal_name | Name | Entity sellers. The legal name including the designation of the legal form. |
| business_registration_number | IN | Entity sellers. DAC7 requires the business registration number. |
| in_type | IN@INType | One of LEI, EIN, IIN, BRN, Other. Required whenever a registration number is filed. |
| permanent_establishments | PermanentEstablishments/PermanentEstablishment | EU Member States where the entity has a permanent establishment. Separate several with a semicolon. |
| address_country_code | Address/CountryCode | ISO 3166-1 alpha-2. |
| address_street | Address/AddressFix/Street | Street of the registered or primary address. |
| address_post_code | Address/AddressFix/PostCode | Postal code. |
| address_city | Address/AddressFix/City | City. The schema requires it inside a fixed-format address. |
| address_free | Address/AddressFree | Whole address as one string. The guide reserves this for cases where the parts cannot be told apart. |
| financial_identifier | FinancialIdentifier/Identifier | IBAN, sort code and account number, or the payment account identifier the consideration was paid to. |
| financial_account_number_type | FinancialIdentifier/Identifier@AccountNumberType | Describes the kind of account number filed, for example IBAN. |
| financial_account_holder_name | FinancialIdentifier/AccountHolderName | Only where the account holder differs from the seller. |
| activity_kind | RelevantActivities/* | One of ImmovableProperty, PersonalServices, SaleOfGoods, TransportationRental. |
| currency_code | ConsQ1..4@currCode, FeesQ1..4@currCode, TaxQ1..4@currCode | ISO 4217, 3 characters. One currency per row. |
| cons_q1 | ConsQ1 | Consideration paid or credited in Q1. |
| cons_q2 | ConsQ2 | Consideration paid or credited in Q2. |
| cons_q3 | ConsQ3 | Consideration paid or credited in Q3. |
| cons_q4 | ConsQ4 | Consideration paid or credited in Q4. |
| numb_q1 | NumbQ1 | Number of relevant activities in Q1. |
| numb_q2 | NumbQ2 | Number of relevant activities in Q2. |
| numb_q3 | NumbQ3 | Number of relevant activities in Q3. |
| numb_q4 | NumbQ4 | Number of relevant activities in Q4. |
| fees_q1 | FeesQ1 | Fees and commissions withheld in Q1. |
| fees_q2 | FeesQ2 | Fees and commissions withheld in Q2. |
| fees_q3 | FeesQ3 | Fees and commissions withheld in Q3. |
| fees_q4 | FeesQ4 | Fees and commissions withheld in Q4. |
| tax_q1 | TaxQ1 | Taxes withheld in Q1. |
| tax_q2 | TaxQ2 | Taxes withheld in Q2. |
| tax_q3 | TaxQ3 | Taxes withheld in Q3. |
| tax_q4 | TaxQ4 | Taxes withheld in Q4. |
| property_address_country_code | PropertyListing/Address/CountryCode | Immovable property rows. ISO 3166-1 alpha-2 of the listing. |
| property_address_street | PropertyListing/Address/AddressFix/Street | Immovable property rows. |
| property_address_post_code | PropertyListing/Address/AddressFix/PostCode | Immovable property rows. |
| property_address_city | PropertyListing/Address/AddressFix/City | Immovable property rows. |
| property_address_free | PropertyListing/Address/AddressFree | The listing address as one string, where the parts cannot be told apart. Same exception as address_free, applied to the listing. |
| land_registration_number | PropertyListing/LandRegistrationNumber | Reportable where available, including equivalents such as a cadastral number. |
| property_type | PropertyListing/PropertyType | One of DPI901 to DPI910. |
| other_property_type | PropertyListing/OtherPropertyType | Free text, and only where property_type is DPI910. |
| rented_days | PropertyListing/RentedDays | Days the listing was rented in the reportable period. The schema takes 1 to 4 digits. |
Template header, for pasting into a query: seller_id,seller_type,res_country_code,tin,tin_issued_by,tin_unknown, …