# Commodity codes Commodity codes classify goods for import and export so traders can: * fill in declarations and other paperwork * check if there’s duty or VAT to pay * find out about duty reliefs There are about 25,000 commodity codes in the UK Tariff. About 16,000 of the total number of commodity codes are declarable end-lines. An end-line is the most specific classification of a product. Commodity codes contain 10 digits. The first 6 digits are regulated by the World Customs Organization (WCO). This system is called the Harmonized System (HS). The system is used by more than 200 countries and economies as a basis for their Customs tariffs. Read more [about the Harmonized System](http://www.wcoomd.org/en/topics/nomenclature/overview/what-is-the-harmonized-system.aspx) on the WCO website. A revision takes place every 5 years. The most recent change took place in January 2022. The last 4 digits are used by countries and trading blocks to subclassify goods, thus it is possible that the same code may refer to different goods depending on the country. For the purposes of goods classification, the UK continues to maintain regulatory alignment with the EU, hence the last 4 digits of codes in the UK are the same as those used in the EU. ## What commodity codes are made up of The full list of products in the UK Tariff is called the 'goods classification'. Sometimes it is also referred to as the 'goods nomenclature' or 'nomenclature'. The [UK goods classification](https://www.trade-tariff.service.gov.uk/browse) is divided into 21 sections. These are shown in the Tariff as Roman numerals. Section numbers do not form part of a commodity code. ```dot graph G { rankdir=LR node [shape=none] HS [label=<
1 2 3 4 5 6
HS chapter HS heading HS
subheading
Managed by WCO
>] CN [label=<
7 8 9 10
CN
subheading
TARIC
subheading
Managed by EU
>] HS -- CN [color=none]; } ``` ### The first pair of numbers: the HS chapter Within each section there are a series of chapters. The first pair of numbers in each commodity code shows which HS chapter of the Harmonized System it is in. ### The second pair of numbers: the HS heading Each HS chapter contains a series of headings. The second pair of numbers in each commodity code (digits 3 and 4) show which HS heading it comes under. ### The third pair of numbers: the HS subheading The third pair of numbers in each commodity code (digits 5 and 6) show which HS subheading it comes under. ### The fourth pair of numbers: the CN subheading The EU refers to its tariff as the combined nomenclature (CN). The fourth pair of numbers in every commodity code (digits 7 and 8) show the CN subheading. The CN subheading is a further development of the Harmonized System. It's used to classify goods when they are declared to customs in the EU. This 8-digit nomenclature cannot be changed over a period of one year. ### The fifth pair of numbers: TARIC codes The fifth pair of numbers (digits 9 and 10) are known as TARIC codes. TARIC is the tariff rate of the European Communities. The first 8 numbers are the same as the combined nomenclature. These 8-digit codes are broken down further into 10-digit codes. ## If a commodity codes appears to have fewer than 10 characters Commodity codes are sometimes shown with fewer than 10 characters. This is to represent a higher level in the classification hierarchy. In these cases, the missing numbers are always zeroes. For example, a commodity code written as 0102 is actually the 10-digit code 0102000000. Any spaces or dots added to commodity codes are for presentation purposes only. ## Chapters 98 and 99 of the goods classification Chapters 98 and 99 are part of the EU’s special coding system and are not defined by the WCO Harmonized System. [Chapter 98](https://www.trade-tariff.service.gov.uk/chapters/98) is for statistical reporting purposes for industrial plant. No codes in this chapter have measures so traders cannot declare on them. Chapter 99 contains codes for certain specific movements of goods. This includes things like personal effects belonging to a person moving house. Chapter 99 was optional for EU member states and the UK did not legislate for its use. It is not available for declarations but remains in the dataset. ## Why the online tariff has indents The Tariff originated as a printed document. Indents were used to identify how many centimetres into the page the heading should appear. This showed approximately how deep a commodity code was in the hierarchy. The following image shows: * a hierarchy from the first commodity code in the Tariff down to the last end-line under the first major HS heading branch * a product line suffix for each commodity code * the indent for each commodity code * a description of the commodity code The physical indent on the description matches the indent field. So, ‘Horses’ is a ‘child’ of ‘Live horses, asses, mules and hinnies’ and ‘Pure-bred breeding animals’ is a child of ‘Horses’. The HS chapter and the HS heading use an indent of zero to show they are not indented. | Commodity | Suffix | Indents | Description | |---|---|---|---| | `0100 00 00 00` | 80 | 0 | **LIVE ANIMALS** | | `0101 00 00 00` | 80 | 0 | **Live horses, asses mules and hinnies** | | `0101 21 00 00` | 10 | 1 |     Horses | | `0101 21 00 00` | 80 | 2 |         Pure-bred breeding animals | | `0101 29 00 00` | 80 | 2 |         Other | | `0101 29 10 00` | 80 | 3 |             For slaughter | | `0101 29 90 00` | 80 | 3 |             Other | | `0101 30 00 00` | 80 | 1 |     Asses | | `0101 90 00 00` | 80 | 1 |     Other | ### Entity-relationship diagram for commodity codes and indents The below E-R diagram shows the data structure of the central goods nomenclature entites and the indents entities. ```dbml Table "Goods Nomenclature" { "Goods Nomenclature Id" int [pk] "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) "Statistical Indicator" binary "Validity Start" date [not null] "Validity End" date } Table "Goods Nomenclature Indents" { "Indent Id" char(3) [pk] "Goods Nomenclature Id" int [pk] "Validity Start" date [not null] "Number of Indents" int "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) } Table "Goods Nomenclature Description Period" { "Description Period Id" char(3) [pk] "Goods Nomenclature Id" int [pk] "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) "Validity Start" date [not null] "Description" varchar(255) } Table "Goods Nomenclature Description" { "Description Period Id" char(3) [pk] "Goods Nomenclature Id" int [pk] "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) "Language Id " int "Description" varchar(255) } Ref: "Goods Nomenclature Indents"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" Ref: "Goods Nomenclature Description Period"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" Ref: "Goods Nomenclature Description"."Description Period Id" > "Goods Nomenclature Description Period"."Description Period Id" Ref: "Goods Nomenclature Description"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" ``` ## Defining if a product is declarable: the product line suffix A product line suffix is a separate pair of numbers shown beside the commodity code. A value of 80 means the commodity code could in theory be declared. A value of less than 80, such as 10 or 20, means the commodity code is being used for grouping and structure purposes only. Measures can only be attached to codes with a suffix of 80. A product is only declarable if both the following apply: * it has the product line suffix 80 * it is an end-line (that is, it does not have any 'child codes' in the hierarchy) In the following example, the declarable commodities are those with a D against them. Although `0101 29 00 00` and `0101 00 00 00` have a product line suffix 80, they cannot be declared because they have child codes. | Commodity | Suffix | Indents | Description | Declarable | |---|---|---|---|---| | `0100 00 00 00` | 80 | 0 | **LIVE ANIMALS** | | `0101 00 00 00` | 80 | 0 | **Live horses, asses mules and hinnies** | | `0101 21 00 00` | 10 | 1 |     Horses | | `0101 21 00 00` | 80 | 2 |         Pure-bred breeding animals | D | | `0101 29 00 00` | 80 | 2 |         Other | | `0101 29 10 00` | 80 | 3 |             For slaughter | D | | `0101 29 90 00` | 80 | 3 |             Other |D | | `0101 30 00 00` | 80 | 1 |     Asses | D | | `0101 90 00 00` | 80 | 1 |     Other | D | ## The hierachical nature of commodity codes Codes exist in a tree structure, with parent and child codes. The parent of "Pure-bred breeding animals" is "Horses" – so in fact, the commodity code `0101 21 00 00` only applies to horses that are pure-bred and for breeding. A pure-bred breeding bull would not fall under `0101 21 00 00`. Hence, understanding the ancestors of a commodity code is important as well. In the tables above, you can see `0101 21 00 00` listed twice – once for "Horses" and once for "Pure-bred breeding animals", and despite having the same code the former is the parent of the latter. This is because "Horses" is an intermediate line – it is not a legally recognised code, but exists just to provide more structure to the tree. This is where the "suffix" comes into play – a commodity code can exist multiple times with different suffixes, and only the code with the suffix marked "80" can be declared or referenced in legislation. The parent of a commodity code at a given date is defined as the commodity code with: * An indent equal to 1 less (except for codes with indents of 0) * A code less than, or if equal a suffix less than * Validity dates on code and indent that contain the given date * A position latest in the commodity code list when sorting by code and suffix So in the tables above, `0101 29 10 00` exists at indent 3, and hence is a child of `0101 29 00 00` at indent 2. And `0101 21 00 00` with suffix 10 is the parent of `0101 21 00 00` with suffix 80, because although the codes are the same the suffixes are different and 10 is less than 80. Note that for legacy reasons, the top two levels of the hierarchy (so codes with eight trailing zeroes, and codes with 6 trailing zeroes) both have indents of 0 but still exist in parent/child relationship: `0100 00 00 00` is the parent of `0101 00 00 00`; hence the 'indent equal to 1 less' requirement does not apply for these parent/child relationships. We have develped an algorithm to generate a table listing the parent code for each commodity code, as shown in the table below. You can view the sql code behind the table in order to examine the process in more detail. ```sql BEGIN TRANSACTION; -- We create a mapping of CCs to the next CC with the same indent -- that we will use later to inherit down down to CCs that don't -- have their own measures. We do this using a window function by -- ordering by CC and then selecting the next row with the same indent. -- We do this as a temporary table rather than a CTE so that we can -- put some indexes on it. CREATE TEMPORARY TABLE ccs ( cc char(10), sid int4, ptr_id integer, indent integer, next char(10), next_suffix char(2), next_sid int4, suffix char(2) ); CREATE INDEX suffix_index ON ccs (suffix, cc); CREATE INDEX cc_index ON ccs (cc); CREATE INDEX next_index ON ccs (next); CREATE INDEX sid_index ON ccs (sid); CREATE INDEX next_sid_index ON ccs (next_sid); WITH live_codes AS ( SELECT * FROM commodities WHERE commodities.item_id LIKE '01%' AND ( commodities.validity_end IS NULL OR date(commodities.validity_end) > date('2021-01-01') ) ), basic_indents AS ( SELECT gni.sid AS indent_id, gni.indented_goods_nomenclature_id, gni.validity_start, MAX(gni.validity_start) OVER ( PARTITION BY gni.indented_goods_nomenclature_id ORDER BY gni.validity_start ASC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) AS validity_end, ( CASE WHEN gn.item_id LIKE '%00000000' THEN -1 ELSE gni.indent END ) AS number_indents, gn.item_id, gn.suffix, gn.validity_start AS gn_start, gn.validity_end AS gn_end FROM commodity_indents AS gni LEFT OUTER JOIN commodities gn ON gni.indented_goods_nomenclature_id = gn.trackedmodel_ptr_id ), goods_indents AS ( SELECT indent_id, indented_goods_nomenclature_id, date(validity_start) AS validity_start, date( CASE WHEN basic_indents.validity_end = basic_indents.validity_start THEN NULL ELSE basic_indents.validity_end END ) AS validity_end, number_indents, indented_goods_nomenclature_id, suffix, gn_start, gn_end FROM basic_indents ), parents AS ( SELECT parents.*, ( CASE WHEN parents.item_id LIKE '%00000000' THEN -1 ELSE parent_indents.number_indents END ) AS number_indents FROM live_codes AS parents LEFT OUTER JOIN goods_indents AS parent_indents ON parents.trackedmodel_ptr_id = parent_indents.indented_goods_nomenclature_id WHERE date(parent_indents.validity_start) <= date('2021-01-01') AND ( date(parent_indents.validity_end) >= date('2021-01-01') OR parent_indents.validity_end IS NULL ) ) INSERT INTO ccs SELECT parents.item_id as cc, parents.sid AS sid, parents.trackedmodel_ptr_id AS ptr_id, parents.number_indents as indent, LEAD(parents.item_id) OVER ( PARTITION BY parents.number_indents ORDER BY parents.item_id, parents.suffix ) AS next, LEAD(parents.suffix) OVER ( PARTITION BY parents.number_indents ORDER BY parents.item_id, parents.suffix ) AS next_suffix, LEAD(parents.sid) OVER ( PARTITION BY parents.number_indents ORDER BY parents.item_id ) AS next_sid, parents.suffix AS suffix FROM parents; -- Now we create the mapping of CCs to all descendent CCs. -- We do this using the table above, selecting all of the CCs -- that exist between the two limits and at a greater indent. -- Again we do this as a temporary table so we can take advantage -- of indexes. CREATE TEMPORARY TABLE cc_children ( parent_sid int4, parent_cc char(10), parent_ptr_id int4, parent_suffix char(2), parent_indent integer, child_sid int4, child_cc char(10), child_ptr_id int4, child_suffix char(2), child_indent integer ); CREATE INDEX parent_sid_index ON cc_children (parent_sid); CREATE INDEX child_sid_index ON cc_children (child_sid); INSERT INTO cc_children SELECT cc1.sid as parent_sid, cc1.cc as parent_cc, cc1.ptr_id as parent_ptr_id, cc1.suffix as parent_suffix, cc1.indent as parent_indent, cc2.sid as child_sid, cc2.cc as child_cc, cc2.ptr_id AS child_ptr_id, cc2.suffix as child_suffix, cc2.indent as child_indent FROM ccs as cc1, ccs as cc2 WHERE cc2.cc >= cc1.cc AND ( cc2.cc < cc1.next OR cc1.next IS NULL ) AND cc2.indent = cc1.indent + 1; -- Finally we use the mapping. We must also select the correct (i.e. latest) description. WITH all_descs AS ( SELECT gad.sid AS description_sid, gad.described_goods_nomenclature_id AS area_sid, gad.description, MAX(gad.validity_start) AS validity_start FROM commodity_descriptions gad GROUP BY gad.described_goods_nomenclature_id ), all_codes AS ( SELECT child_sid AS sid, child_ptr_id AS ptr_id, parent_sid AS parent FROM cc_children UNION SELECT sid, ptr_id, NULL AS parent FROM ccs WHERE indent = -1 ) SELECT all_codes.sid AS sid, children.item_id AS commodity_code, children.suffix AS suffix, all_descs.description, date(children.validity_start) AS validity_start, date(children.validity_end) AS validity_end, all_codes.parent AS parent_sid, parents.item_id AS parent_code FROM all_codes LEFT OUTER JOIN commodities children ON all_codes.sid = children.sid LEFT OUTER JOIN commodities parents ON all_codes.parent = parents.sid LEFT OUTER JOIN all_descs ON all_codes.ptr_id = all_descs.area_sid ORDER BY children.item_id, children.suffix LIMIT 25; COMMIT; DROP TABLE ccs; DROP TABLE cc_children; ``` Note that the above code only applies to codes in HS chapter 01, and only shows the first 25 results, to remove these restrictions from the code, delete the 'commodities.item_id LIKE '01%'' condition at line 36 and the 'LIMIT 25' condition at line 226. ## How new commodity codes are created An origin defines the commodity code which a new commodity code was taken from. When a commodity code is split in 2, the ‘origin’ is the parent commodity code. It is mandatory that at least one origin is created for every new commodity code. ### Absorbing old commodity codes A successor defines the commodity code which an existing commodity code has been absorbed into. It is not mandatory for a successor code to be created, though there is the option to create them. ### Residual codes When a commodity code is split into parts, a specific code and a residual code are created. The residual code is usually labelled 'other' in the hierarchy. The following example shows commodity code `2001 90 70 00` has been split into 2 child codes: * the specific code is assigned 10 as the final 2 digits * the residual code is assigned 90 as the final 2 digits | Code | Suffix | Indents | Description | |---|---|---|---| | `2000 00 00 00` | 80 | 0 | **PREPARATIONS OF VEGETABLES, FRUIT, NUTS OR OTHER PARTS OF PLANTS** | | `2001 00 00 00` | 80 | 1 |     **Vegetables, fruit, nuts and other edible parts of plants, prepared or preserved by vinegar or acetic acid** | | `2001 90 00 00` | 80 | 2 |         Other | | `2001 90 70 00` | 80 | 3 |             Sweet peppers | | `2001 90 70 10` | 80 | 4 |                 Not containing added sugar | | `2001 90 70 90` | 80 | 4 |                 Other | If more child codes are added to the parent as siblings to 10 and 90, these are assigned 20, 30, 40 as the final 2 digits while space remains. If a code is split on the last digit, rather than the last 2 digits, it is usually split into 1 and 9. There are more than 6,500 residual codes in the database. ### Entity-relationship diagram for origins and successors This E-R diagram details the relationships between the central goods nomenclature entity and the origin/successor entities ```dbml Table "Goods Nomenclature" { "Goods Nomenclature Id" int [pk] "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) "Statistical Indicator" binary "Validity Start" date [not null] "Validity End" date } Table "Goods Nomenclature Origin" { "Goods Nomenclature Id" int [pk] "Derived Commodity Code" char(10) "Derived Suffix" char(2) "Commodity Code" char(10) "Suffix" char(2) } Table "Goods Nomenclature Successor" { "Goods Nomenclature Id" int [pk] "Absorbed Commoddity Code" char(10) "Absorbed Suffix" char(2) "Commodity Code" char(10) "Suffix" char(2) } Ref: "Goods Nomenclature Origin"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" Ref: "Goods Nomenclature Successor"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" ``` ## Entity-Relationship diagram of 'external' links This E-R diagram details the relationships between the central goods nomenclature entity and other tariff data structure entities (namely measures and footnotes) ```dbml Table "Goods Nomenclature" { "Goods Nomenclature Id" int [pk] "Commodity Code (Goods Nomenclature Item Id)" char(10) "Suffix" char(2) "Statistical Indicator" binary "Validity Start" date [not null] "Validity End" date } Table "Measure" { "Measure Id" int [pk] "Goods Nomenclature Id" int [pk] "Goods Nomenclature Item Id" char(10) "..." "..." } Table "Footnote Association Goods Nomenclature" { "Footnote Id" int [pk] "Footnote Type" "Goods Nomenclature Id" int [pk] "Goods Nomenclature Item Id" char(10) "Suffix" char(2) "Validity Start" date [not null] "Validity End" date } Ref: "Measure"."Goods Nomenclature Id" > "Goods Nomenclature"."Goods Nomenclature Id" Ref: "Footnote Association Goods Nomenclature"."Footnote Id" > "Goods Nomenclature"."Goods Nomenclature Id" ``` ## Validation rules | Code | Description | |---|---| | NIG1 | [Validity overlaps with self](Validity-rules;-Validity-overlaps-with-self.md) rule stating the validity periods must not overlap between goods with the same goods nomenclature id. | | NIG10 | Successor codes must become applicable the day after the end of the old code. | | NIG11 | [Mandatory subrecord](Validation-rules;-Mandatory-subrecord.md) rule that each goods nomenclature id must have at least one indent record. The start date of the first indentation must be equal to the start date of the nomenclature. No two associated indentations may have the same start date. The start date must be less than or equal to the end date of the nomenclature. | | NIG12 | [Mandatory subrecord](Validation-rules;-Mandatory-subrecord.md) rule for goods nomenclature descriptions. The start date of the first description period must be equal to the start date of the nomenclature. No two associated description periods may have the same start date. The start date must be less than or equal to the end date of the nomenclature. | | NIG18 | Footnotes with a footnote type for which the application type = “CN footnotes” must be linked to CN lines (all codes up to 8 digits). | | NIG2 | [Validity contained](Validity-rules;-Validity-contained.md) rule requiring the validity period of the goods nomenclature to be within the validity period of the product line above in the hierarchy. | | NIG22 | [Validity contained](Validity-rules;-Validity-contained.md) rule requiring the period of the association with a footnote to be within the validity period of the nomenclature. | | NIG23 | [Validity contained](Validity-rules;-Validity-contained.md) rule requiring the period of the association with a footnote to be within the validity period of the footnote. | | NIG24 | [Validity excluded](Validity-rules;-Validity-excluded.md) rule that when the same footnote is associated more than once with the same nomenclature then there may be no overlap in their association periods. | | NIG30 | [Validity contained](Validity-rules;-Validity-contained.md) rule requiring the validity period of a goods measure to be within the validity period of the goods nomenclature that it references. | | NIG31 | [Validity contained](Validity-rules;-Validity-contained.md) rule requiring the validity period of a goods measure to be within the validity period of the goods nomenclature that it references. | | NIG34 | [Deletion while in use](Validation-rules;-Deletion-while-in-use.md) rule for goods nomenclature used in goods measures. | | NIG35 | [Deletion while in use](Validation-rules;-Deletion-while-in-use.md) rule for goods nomenclature used in additional nomenclature measures. | | NIG5 | [Must exist](Validation-rules;-Must-exist.md) rule that when creating a goods nomenclature code, an origin must exist. This rule is only applicable to update extractions. Almost all goods nomenclatures must have an origin, excluding two scenarios: they are a top level code (depth/indent of 1), they were made before 2010-01-01 (legacy data). Therefore check for these two conditions, and if neither are met ensure an origin exists. | | NIG7 | The origin must be applicable the day before the start date of the new code entered. | For more detail see the [system documentation](https://uktrade.github.io/tamato/html/business_rules/commodities.html#goods-nomenclature).