Skip to content

Party identifiers for customs & tax authorities #45

@codeal-ltd

Description

@codeal-ltd

Originally proposed in https://github.com/commerce-operations-foundation/mcp-reference-server/pull/24

The PR introduces buyerEORI and buyerTAXid. The reviewer flagged that buyer is not a node used elsewhere in the schema, and that buyerTAXid breaks camelCase convention. The proposed resolution from the PR author is to normalise these as buyer_id_customs / seller_id_customs for EORI/EIN equivalents, and buyer_id_tax / seller_id_tax for tax identifiers. These are distinct: customs IDs enable automated clearance, tax IDs are for VAT/GST compliance. Decision needed on node naming and whether these sit under a new party node or at order header level.

The schema needs to distinguish importer from exporter, and customs ID from tax authority ID. Proposal is to introduce a dedicated crossBorderParties object rather than flat header fields. This resolves the internal consistency objection, groups the identifiers logically, and is extensible without polluting the order header.

"crossBorderParties": {
  "type": "object",
  "description": "Party identifiers required for customs clearance and tax compliance on cross-border shipments.",
  "properties": {
    "importerCustomsId": {
      "description": "Importer's customs registration number (EORI in EU/UK, EIN in US, or equivalent). Enables automated customs clearance.",
      "type": "string"
    },
    "exporterCustomsId": {
      "description": "Exporter's customs registration number (EORI in EU/UK, EIN in US, or equivalent).",
      "type": "string"
    },
    "importerTaxId": {
      "description": "Importer's tax authority registration number (VAT, GST, or equivalent). Required for customs assessed value and tax compliance.",
      "type": "string"
    },
    "exporterTaxId": {
      "description": "Exporter's tax authority registration number (VAT, GST, or equivalent).",
      "type": "string"
    }
  },
  "additionalProperties": false
}

importer / exporter is more precise than buyer / seller in a cross-border context. A marketplace seller may not be the exporter of record (EOR), and the importer of record (IOR) may be a broker, 3PL, or the end customer, none of which map cleanly to "buyer". Using importer / exporter aligns with WCO terminology, carrier API field naming (FedEx uses importerOfRecord, UPS uses shipper / importer), and customs documentation.

CustomsId and TaxId as suffixes are self-describing and follow the camelCase convention already in the schema. They are also identifier-type-agnostic, which matters because the schema should not embed region-specific acronyms (EORI, EIN) into field names, these belong in the description and in the TMS translation layer.

Alternative if a flat header structure is preferred over a sub-object:

"importerCustomsId": { "type": "string" },
"exporterCustomsId": { "type": "string" },
"importerTaxId": { "type": "string" },
"exporterTaxId": { "type": "string" }

Complete cross-border schema map, final state (please refer to other Issues for details):

order (header)
├── shippingCarrier               ← existing flat field
├── shippingMethod                ← existing flat field
├── incoterms                     ← existing flat field
├── reasonForExport               ← enum (this PR)
├── reasonForExportDetail         ← conditional free text (OTHER only)
├── crossBorderParties            ← party identity and regulatory IDs
│   ├── importerCustomsId
│   ├── exporterCustomsId
│   ├── importerTaxId
│   └── exporterTaxId
├── crossBorderCharges            ← taxes and duties collected at checkout
│   ├── taxCollected
│   ├── dutyCollected
│   ├── duties[]
│   │   ├── dutyType
│   │   ├── amount
│   │   └── description
│   ├── taxScheme
│   ├── iossNumber
│   └── ddpElected
├── shippingCharges               ← shipping financials for customs valuation
│   ├── shippingCost
│   ├── insuranceAmount
│   ├── additionalFees
│   ├── customsValuationBasis
│   └── sellerPaidShipping
├── carrierBilling                ← carrier account and billing responsibility
│   ├── freightPayor
│   │   ├── payorType
│   │   ├── carrierAccountNumber
│   │   └── carrierName
│   └── dutyTaxPayor
│       ├── payorType
│       ├── carrierAccountNumber
│       └── carrierName
└── fulfillmentWindow             ← date constraints for WMS and carrier
    ├── requestedShipDate
    ├── shipNotBeforeDate
    ├── shipNotAfterDate
    ├── requestedDeliveryDate
    └── doNotDeliverAfterDate

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions