Skip to main content

Reference data

Every coded value on a declaration is checked against a vocabulary before ITS accepts it. A value that is not in its vocabulary is refused with VAL-ETD-003, naming the field.

Read the vocabularies

The vocabularies are served at /api/reference, outside /api/v1. Any valid token reads them. No permission is needed, so you can load them before the Secretariat has configured anything else.

{entityType}Fills
countriesEvery country code field (ISO 3166-1 alpha-2)
currenciescurrency and guarantee.currency (ISO 4217)
customs-officesdeparture, destination and every stamp's station
hs-codescommodities[].hs_code
package-kindscommodities[].kind_of_packages
terms-of-paymentterms_of_payment
transport-modestransport_mode, which ITS assigns
au-member-statesAfrican Union membership, used for country display names
OperationPathQuery parameters
ListGET /api/reference/{entityType}filter, order-by, query, page-number, page-size
List active onlyGET /api/reference/{entityType}/activefilter, order-by, query, page-number, page-size
List currently effectiveGET /api/reference/{entityType}/effectivepage-number, page-size
SearchGET /api/reference/{entityType}/searchquery, filter, order-by, page-number, page-size
Dataset versionGET /api/reference/{entityType}/versionnone
One rowGET /api/reference/{entityType}/{id}none
Available datasetsGET /api/referencenone
A dataset's fieldsGET /api/reference/{entityType}/schemanone
  • page-number is 1-based and page-size defaults to 20. Set it explicitly for the large vocabularies: 5,612 HS codes at 20 a page is 281 requests.
  • filter takes field::value expressions, such as ?filter=sectionCode::K, and order-by takes a field name. GET /api/reference/{entityType}/schema lists the fields a dataset has.
  • Responses use the same header and data envelope as the rest of the API, with pagination on lists.
  • A call with no token is 401. An unknown dataset is 404 RES-ETD-029.

page and size still work here as deprecated aliases, and nowhere else. Write page-number and page-size.

Cache the large ones

The vocabularies change a few times a year. Cache them and check for changes instead of fetching them again:

GET /api/reference/hs-codes/version
Authorization: Bearer <access_token>

/version returns a row count and a lastModified stamp. Refetch only when they change.

It is read-only

POST, PUT, PATCH and DELETE on /api/reference are refused for everyone, permanently. These vocabularies are shared across many systems, so ITS reads them and never writes them.

If a code your national system uses is genuinely missing, raise it as a data request with the AfCFTA Secretariat. It cannot be added over the API.

Small lists you can hardcode

These lists are short and stable:

Transport modes. ITS carries road transport only, so it assigns 3 and returns it. You do not send it.

CodeMeaningCodeMeaning
1Maritime transport6Multimodal transport
2Rail transport7Fixed transport installation
3Road transport8Inland water transport
4Air transport9Transport mode not applicable
5Mail

Terms of payment (Incoterms): CAD, CFR, CIF, CIP, CPT, DAP, DDP, DPU, EXW, FAS, FCA, FOB.

Seal types: METALLIC, ELECTRONIC. Anything else is refused with VAL-ETD-005.

HS codes

commodities[].hs_code takes 6 to 12 digits, so a national tariff line of 8 or 10 digits is accepted as it is. Only the first six digits are checked against the HS vocabulary. Digits 7 to 12 are kept, printed and returned exactly as you sent them, and never interpreted.

Customs offices

A customs office is a three-character station_code, [A-Z0-9]{3}, inside a country: every office box is { "country_code": "KE", "station_code": "MBA" }.

Each State Party maintains its own customs offices in the ITS register.

  • An office of your own that the register does not list is accepted. Your country is the authority on the offices it operates. The code is stored as sent, the response is still 201 or 200, and header.additional_details names the code so you learn about it at once.
  • An office in another country is refused (VAL-ETD-004). You cannot vouch for an office you do not operate.
  • The one exception is the office of destination when the destination country is not on ITS. It is stored as sent and reported in additional_details. It must still be in the destination country (VAL-ETD-081).
  • Entry and exit need a border office. A stamp at an office the register records as INLAND is refused with BUS-ETD-083. An office nobody has described yet is accepted.

To see the codes of yours that the register does not list:

GET /etd/reconciliation/stations
{
"data": [
{
"country_code": "UG",
"station_code": "QQ1",
"occurrences": 412,
"first_seen_at": "2026-07-02T08:11:04+03:00",
"last_seen_at": "2026-08-13T06:40:19+03:00"
}
]
}

occurrences and last_seen_at tell a typo from a missing border post. Seen once a month ago is a typo to correct on one declaration. Seen four hundred times in the last hour is an office to add to your register. Add it and the row disappears from the next read.

Taxpayer identification numbers

ITS records a TIN exactly as you send it. It does not check the format and holds no register of formats. Validate your own taxpayer numbers before you submit.

declarant.tin (TD field 34) is still required: a declaration has to say who filed it.

Country names

Responses carry country_name beside the codes in office boxes, and country_of_origin_name on each commodity. These are the African Union's names for its member states, such as Côte d'Ivoire and DR Congo, and the ISO name for any other country.

Do not key anything on these names. The code is the identifier. You send only the two-letter code.