Adding EU PID Fields to UPS, FedEx and DHL APIs

How to add M-PID, NS-PID and S-PID fields to UPS, FedEx and DHL shipment APIs before the EU's Nov 1, 2026 PID deadline.

Adding EU PID Fields to UPS, FedEx and DHL APIs

Five weeks out from the November 1, 2026 enforcement date, most of what's been written about the EU's new Product Identifier (PID) requirement is aimed at merchants deciding whether to bother with an NS-PID field. That's not the problem you have. You need to know exactly which attribute names UPS, FedEx and DHL Express expect in their shipment API payloads, what happens when one is blank, and how to prove your integration handles it before a real customer's parcel gets stuck at Frankfurt or Roissy. This is that guide, at the field level.

Why this can't wait until October

Starting November 1, 2026, every B2C shipment imported into the EU needs a Product Identifier attached at the line-item level, or the carrier can't clear it. UPS's own developer portal now carries a standing notice: effective November 1, 2026, the EU will require Product Identifier (PID) information for certain business-to-consumer (B2C) shipments entering the EU, with updated Ship documentation available. FedEx is blunter about the consequence for API callers. Its EU PID Guide states plainly that without PIDs, you will not be able to create a label and complete your shipment after the deadline. That's not a warning email or a compliance flag in a report. It's a hard API rejection sitting between your order and a printed label.

The legal basis, if you need it for a ticket or a vendor escalation, is Commission Delegated Regulation (EU) 2026/1022 of 30 June 2026, which amends the Union Customs Code Delegated Act to formally define the M-PID, NS-PID, and S-PID and require them on H1/H6/H7 declarations. Practically: these are reported using TARIC document codes C127 (M-PID), C128 (NS-PID), and C129 (S-PID), plus exception code Y081 when no NS-PID exists. You won't touch TARIC codes directly in most carrier APIs, but knowing them helps when a rejection message references a declaration field instead of a JSON attribute.

Carriers have been accepting this data since summer. From July 1, 2026, for each product imported into the EU in a B2C shipment, regardless of value, these codes must be provided to customs authorities during the clearance process, though enforcement only bites on November 1. That voluntary window is your sandbox test period. Use it.

What you need before you touch the API

Get these lined up first, or the build stalls halfway through:

  • Sandbox or dev credentials for UPS Developer Portal, FedEx Developer Portal and DHL Express API, confirmed to be on the current PID-aware version. All three carriers have already updated their shipment endpoints to accept the new fields.
  • A product catalog export with three columns per SKU: your own code, the supplier's code, and a GTIN/EAN/UPC/ISBN if one exists.
  • A documented fallback for products with no barcode. The EU has an answer for this: exception code Y081, applied when no S-PID exists for a given item.
  • A scope flag on the shipment type. If your EU-bound volume is exclusively B2B to VAT-registered consignees, none of this applies to you. PIDs apply to B2C shipments — goods sold directly to non-VAT-registered EU consumers — while B2B shipments to VAT-registered EU businesses fall outside the requirement. Gate your logic on B2C/B2B classification, not on destination country.

Step by step: adding M-PID, NS-PID and S-PID to your shipment calls

  1. Confirm shipment scope. Build a boolean on the order object, something like is_b2c_eu_import, derived from consignee VAT status and destination. Don't default every EU-bound shipment to "needs PID" — you'll create unnecessary validation failures on legitimate B2B freight.
  2. Map your three fields before writing any request code. The M-PID is your own SKU or item code. The NS-PID is the code your supplier or manufacturer uses for the same item — the item code assigned by the factory which produced the goods, with no standard format. The S-PID is a recognized barcode standard: GTIN, EAN, UPC or ISBN, only populated when one genuinely exists for the product.
  3. Locate the exact request attributes per carrier. This is where documentation and reality diverge across vendors, so don't assume a shared schema. Per the Shipmondo.dev customs API reference, the underlying attribute names across carriers are m_pid (Merchant Product ID), ns_pid (Non-Standard Manufacturer Product ID), and s_pid (Standard Manufacturer Product ID, such as an EAN or ISBN). Two carrier-specific traps to build tests around: product identifiers on UPS require the shipment to use the B2C service, and are mutually exclusive with return shipments, and providing product identifiers to FedEx for EU import also requires a receiver email. Miss either precondition and the PID fields you dutifully populated will still get rejected, for reasons that have nothing to do with the PID values themselves.
  4. Handle the type field correctly on FedEx-bound payloads. FedEx's schema pairs m_pid with a type descriptor. m_pid_type describes which kind of identifier m_pid is, and must be one of SKU, GTIN, UPC, EAN, MPN, REGISTERED_NUMBER, OTHER — and m_pid and m_pid_type are codependent, so if one is given, the other is required. Submitting an m_pid without its type (or vice versa) is a common first-pass bug; write a unit test for it now.
  5. Test in sandbox against real payload shapes. A representative customs goods object, per the Shipmondo.dev docs, looks like this (sandbox, tested against their v2026-08 endpoint):
{
  "customs": {
    "currency_code": "DKK",
    "goods": [
      {
        "quantity": 2,
        "country_code": "GB",
        "content": "T-shirt",
        "commodity_code": "61091000",
        "unit_value": 30.10,
        "unit_weight": 1000,
        "attributes": [
          { "name": "m_pid", "value": "5901234567890" },
          { "name": "ns_pid", "value": "ALC-LYON-452" },
          { "name": "s_pid", "value": "5901234567890" }
        ]
      }
    ]
  }
}
  1. Build the missing-data fallback. Decide now what your integration does when a supplier hasn't given you an NS-PID. Don't block the order silently. Log it to a manual review queue and flag the SKU for supplier follow-up, because the NS-PID is the field most teams are missing — it depends on someone at your supplier actually sending you their part number.
  2. Cut over to mandatory validation on your own side before November 1. Reject or flag orders internally that lack required PID data before they ever reach the carrier API. It's cheaper to catch a blank m_pid in your own pre-shipment validation than to debug a 400 response from a carrier sandbox at 4pm on October 31.

Field mapping at a glance

FieldUPS Shipping APIFedEx Ship APIDHL Express API
M-PID attributem_pid equivalent, B2C service requiredm_pid + m_pid_type (codependent)m_pid equivalent
NS-PID attributens_pid equivalentns_pid equivalentns_pid equivalent
S-PID attributes_pid equivalent, optional if no barcodes_pid equivalent, optional if no barcodes_pid equivalent, optional if no barcode
Extra preconditionMutually exclusive with return shipmentsRequires receiver email on the shipmentNot published in current sandbox docs
Mandatory fromNovember 1, 2026November 1, 2026November 1, 2026

These are grouped by function using the Shipmondo.dev changelog as the cross-carrier reference point; confirm exact attribute casing against each carrier's own current API reference before you ship code, since product identifiers are accepted today for DHL Express, FedEx, UPS and unspecified-carrier shipments, with a couple of carrier-specific requirements that shift as each vendor finalizes documentation.

The failure mode: what actually happens when a PID is missing

After November 1, a missing or malformed PID doesn't produce a soft warning. It blocks label creation outright, per FedEx's own guidance cited above, and for shipments that do reach a border without correct data, the outcome is worse: held parcels, rejected declarations, or delays while the carrier chases down missing information. The practical test to run in your harness right now: submit a known-bad payload with a blank NS-PID against each carrier's sandbox and record the exact error code and message returned. You want that string matched in production alerting before go-live, not discovered live when a customer emails asking where their order is.

One overlooked exception path: PIDs remain required for the customs clearance of B2C returned goods into the EU, though the process for these returns is still being defined as of the carriers' latest published guidance. If you run reverse logistics through any of these three APIs, flag this as an open risk rather than assuming your outbound fix covers returns too.

How you know it worked

Three checks, run against sandbox before you touch production:

  • The shipment response accepts all three PID attributes with no validation errors, including on FedEx payloads where m_pid_type is present and correctly paired.
  • The generated label and commercial invoice actually reflect the PID codes you sent, not blank fields — inspect the PDF or ZPL output directly, don't trust the 200 response alone.
  • A small batch of test B2C shipments, run through each carrier's current sandbox, completes without a manual customs intervention flag.

Where multi-carrier platforms change the math

If you're integrated directly with UPS, FedEx and DHL Express, you're mapping this same M-PID/NS-PID/S-PID logic three separate times, with three sets of field names, three sets of preconditions, and three release schedules to track. Platforms that sit behind a connectivity layer, including nShift, EasyPost, Shipmondo and Cargoson, absorb exactly this kind of fast-moving regulatory change once, centrally, rather than leaving each shipper to chase carrier changelogs individually. That's not an argument for abandoning direct integrations you've already built. It's a reason to weigh the maintenance cost of the next regulatory change against the cost of a broker layer, before the one after November 1 lands.

Next step: pull your product catalog export today, not in October, and run the first ten SKUs through each carrier's sandbox this week. The gaps you find in supplier data will take longer to close than the API changes will.