Contents
CommerceBetaVersion v1

Shipment Tracking API

Public parcel tracking for shoppers, and the inbound webhook carriers use to report tracking events.

Two sides of shipment tracking in Nucleo Commerce:

  • Public tracking — the API behind the Nucleo-hosted tracking page (https://app.nucleoplatform.com/track/{token}): brand, order, status, estimated delivery, items and the event history of one shipment, addressed by a signed token. No login; no personal data beyond the shopper's first name and destination city. Use it to show tracking inside your own storefront.
  • Tracking webhook — the endpoint a tracking aggregator (Qapla'), DHL, or any other carrier (or your own middleware) calls to push parcel events into Nucleo. Each call is authenticated with the secret of the carrier connection it is addressed to.

Tracking events are normalised to one set of statuses for every carrier, update the shipment, mark orders as delivered (which starts the return window), open anomalies for problems and trigger the merchant's customer notifications (out for delivery, delivered, ready for pickup, delivery problem).

Authentication

  • nucleoSignatureAPI key · header · X-Nucleo-Signature

    Generic carrier connections. Lowercase hex HMAC-SHA256 of the exact raw request body, keyed with the connection's webhook secret. Compute it over the bytes you send, after JSON serialisation.

  • dhlWebhookKeyAPI key · query · key

    DHL connections. The connection's webhook secret, as a query parameter.

Base URL
https://api-commerce.nucleoplatform.com/api/oms/v1Production
Who calls it
Storefronts, Carriers
Endpoints
2
OpenAPI 3.1 specification
tracking.yaml

Public tracking

Read-only tracking of one shipment by its signed token.

Where the token comes from. Nucleo builds the tracking link …/track/{token} for every shipped parcel; it is the link in the shipping notifications Nucleo sends to shoppers and the tracking page link on the shipment in Orders in Nucleo. The token is the last path segment. It is signed by Nucleo, cannot be guessed or altered, and does not expire; it stops working only if the shipment is voided.

get/public/tracking/{token}

Get a shipment's public tracking

Status, dates, carrier and up to 50 most recent tracking events (newest first) of one shipment, with the merchant's branding. Only what the shopper needs: no email, phone or full address.

status is the normalised status of the latest event; before any event it is picked_up (or delivered if the shipment is already marked delivered).

Language: lang if supported, otherwise the order's language, otherwise one derived from the shipping country, otherwise en. It is returned as locale; event descriptions are shown as the carrier sent them.

Rate limit: 60 requests per minute per IP (X-RateLimit-* headers on every response). Read-only and idempotent.

GET https://api-commerce.nucleoplatform.com/api/oms/v1/public/tracking/{token}
Authentication: None — public endpoint
Rate limit: 60 requests per 1m, per IP

Path parameters

  • tokenstringrequired

    Signed tracking token, the last segment of the tracking link.

    min length 20max length 200pattern ^[A-Za-z0-9_.-]{20,200}$
    Example: MTA0Mjo3ZjNjMmE5MS00YjZkLTRlMmEtOWMxZi0zZDhlNWEyYjZjNDA.Qm9Yc1Z3Tm1LcFJ0WmFHaEpk

Query parameters

  • langstring

    Preferred language.

    One ofitendefres
    Example: it

Responses

  • 200Tracking information.
    Headers
    • X-RateLimit-Limit Requests allowed per minute.
    • X-RateLimit-Remaining Requests left in the current minute.
    • dataPublicTrackingrequired
      Child attributes
      • brandobjectrequired
        Child attributes
        • namestringrequired
          Example: Acme Apparel
        • logo_urlstring (uri) | nullrequired
        • accent_colorstringrequired

          Hex colour (#111111 when not set).

          Example: #0F766E
        • support_emailstring (email) | nullrequired
        • support_urlstring (uri) | nullrequired
      • localestringrequired
        One ofitendefres
      • order_namestringrequired
        Example: #1042
      • customer_first_namestringrequired

        Shipping first name, or empty.

        Example: Giulia
      • destinationstringrequired

        City, COUNTRY of the shipping address (either part may be missing).

        Example: Milano, IT
      • carrierstring | nullrequired
        Example: DHL Express
      • tracking_numbersarray of stringrequired

        One per parcel.

      • carrier_urlstring (uri) | nullrequired

        The carrier's own tracking page, if known.

      • statusstringrequired

        Normalised parcel status, the same for every carrier: pending (label created, not yet collected), picked_up, in_transit, out_for_delivery, delivered, exception (delivery problem), held (at a depot or pickup point), returned_to_sender.

        One ofpendingpicked_upin_transitout_for_deliverydeliveredexceptionheldreturned_to_sender
      • status_atstring (date-time) | nullrequired
      • shipped_atstring (date-time) | nullrequired
      • delivered_atstring (date-time) | nullrequired
      • estimated_delivery_atstring (date-time) | nullrequired
      • itemsarray of objectrequired

        Items in this shipment.

        Attributes of each item
        • titlestringrequired
        • quantityintegerrequired
          min 1
      • eventsarray of objectrequired

        Most recent first.

        max items 50
        Attributes of each item
        • occurred_atstring (date-time) | nullrequired
        • statusstringrequired

          Normalised parcel status, the same for every carrier: pending (label created, not yet collected), picked_up, in_transit, out_for_delivery, delivered, exception (delivery problem), held (at a depot or pickup point), returned_to_sender.

          One ofpendingpicked_upin_transitout_for_deliverydeliveredexceptionheldreturned_to_sender
        • descriptionstring | nullrequired
        • locationstring | nullrequired
  • 404not_found: invalid or tampered token, unknown store, unknown or voided shipment. A token that does not match the path pattern gets the generic route-not-found message instead.

    One of the following shapes:

    TrackingError
    • error"not_found"required
    Message
    • messagestringrequired
  • 429Too many requests from this IP.
    Headers
    • Retry-After Seconds to wait.
    • X-RateLimit-Limit Requests allowed per minute.
    • X-RateLimit-Remaining Requests left in the current minute.
    • X-RateLimit-Reset Unix time when the limit resets.
    • messagestringrequired
Request
curl -X GET 'https://api-commerce.nucleoplatform.com/api/oms/v1/public/tracking/MTA0Mjo3ZjNjMmE5MS00YjZkLTRlMmEtOWMxZi0zZDhlNWEyYjZjNDA.Qm9Yc1Z3Tm1LcFJ0WmFHaEpk?lang=it' \
  -H 'Accept: application/json'
Response
{
  "data": {
    "brand": {
      "name": "Acme Apparel",
      "logo_url": "https://cdn.acme.example/logo.svg",
      "accent_color": "#0F766E",
      "support_email": "help@example.com",
      "support_url": "https://shop.acme.example/pages/contact"
    },
    "locale": "it",
    "order_name": "#1042",
    "customer_first_name": "Giulia",
    "destination": "Milano, IT",
    "carrier": "DHL Express",
    "tracking_numbers": [
      "1234567890"
    ],
    "carrier_url": "https://www.dhl.com/it-en/home/tracking.html?tracking-id=1234567890",
    "status": "out_for_delivery",
    "status_at": "2026-10-06T07:42:00+00:00",
    "shipped_at": "2026-10-05T15:10:00+00:00",
    "delivered_at": null,
    "estimated_delivery_at": "2026-10-06T18:00:00+00:00",
    "items": [
      {
        "title": "Organic Cotton Tee · M",
        "quantity": 1
      },
      {
        "title": "Fleece Hoodie · L",
        "quantity": 2
      }
    ],
    "events": [
      {
        "occurred_at": "2026-10-06T07:42:00+00:00",
        "status": "out_for_delivery",
        "description": "Shipment is out with courier for delivery",
        "location": "Milano, IT"
      },
      {
        "occurred_at": "2026-10-05T21:03:00+00:00",
        "status": "in_transit",
        "description": "Processed at MILANO - ITALY",
        "location": "Milano, IT"
      },
      {
        "occurred_at": "2026-10-05T15:10:00+00:00",
        "status": "picked_up",
        "description": "Shipment picked up",
        "location": "Bologna, IT"
      }
    ]
  }
}

Carrier webhooks

Inbound tracking events, one URL per carrier connection: https://api-commerce.nucleoplatform.com/api/oms/v1/webhooks/tracking/{connection_id}.

The connection (Qapla', DHL or another carrier) and its secret are configured on the merchant's account under Settings › Orders › Channels and logistics; the connection ID is the UUID of that connection. Webhook secrets for carriers and Qapla' are set up with Nucleo during onboarding — ask Nucleo support for the URL and the secret.

Three payload formats are accepted, chosen by the connection type:

ConnectionBodyAuthentication
Qapla'Qapla' webhook (v1.2/1.3), one eventapiKey field in the body = the connection's API key
DHLDHL Shipment Tracking – Unified (shipments[])?key= query parameter = the connection's webhook secret
Any other carrierNucleo generic format (events[])X-Nucleo-Signature header = hex HMAC-SHA256 of the raw body with the connection's webhook secret
post/webhooks/tracking/{connection}

Push tracking events for a carrier connection

Receives parcel events for the shipments of one carrier connection. The expected body and authentication depend on the connection type (see the table in the tag description):

  • Generic carriers — body {"events": [ … ]} (or a single event object), header X-Nucleo-Signature: hex(HMAC-SHA256(raw body, webhook_secret)). status can be a Nucleo status, a carrier code translated by the connection's status map, or empty (Nucleo infers it from description, in Italian, English, German, French or Spanish).
  • Qapla' — the Qapla' webhook body, authenticated by its apiKey field (this scheme cannot be expressed as an OpenAPI security requirement). The reply is {"result":"OK"} as Qapla' expects.
  • DHL — the DHL Shipment Tracking – Unified body (shipments[]), authenticated by ?key=.

Matching. Events are matched to shipments by tracking_number (the most recent parcel with that number). Events for unknown tracking numbers are ignored without error.

Idempotency. An event identical to one already stored (same shipment, tracking number, minute, status and description) is ignored, so retries and overlapping deliveries are safe. applied counts only new events.

Effects. The shipment takes the status of its most recent event. delivered marks the shipment and order delivered (starting the return window) and closes open tracking anomalies; exception, held and returned_to_sender open an anomaly for the merchant. Recent events may send the merchant's customer notifications (out for delivery, delivered, ready for pickup, delivery problem), each at most once.

Rate limit: 600 requests per minute per calling IP.

POST https://api-commerce.nucleoplatform.com/api/oms/v1/webhooks/tracking/{connection}
Authentication: X-Nucleo-Signature header or key query parameter
Rate limit: 600 requests per 1m, per IP

Path parameters

  • connectionstring (uuid)required

    ID of the carrier or Qapla' connection in Nucleo.

    Example: 5f0c7e2a-8b3d-4c1e-9a6f-2d4b8e1c7a35

Request bodyapplication/json

One of the following shapes:

GenericWebhook
  • eventsarray of GenericEventrequired
    Attributes of each item
    • tracking_numberstringrequired

      Parcel tracking number, as stored on the Nucleo shipment.

      Example: 0612345678901
    • statusstring

      A Nucleo status (see TrackingStatus), a carrier status code mapped by the connection's status map, or empty to let Nucleo infer it from description.

      Example: delivered
    • descriptionstring

      Event text (stored up to 500 characters).

      Example: Delivered to recipient
    • occurred_atstring (date-time)

      When the event happened. Defaults to the time of receipt.

    • locationstring

      Where it happened (stored up to 160 characters).

      Example: Milano
    • exception_codestring

      Detail for exception and held.

      One ofaddress_wrongrecipient_absentrefuseddamagedcustomsheld_at_depotat_pickup_pointlostother
GenericEvent
  • tracking_numberstringrequired

    Parcel tracking number, as stored on the Nucleo shipment.

    Example: 0612345678901
  • statusstring

    A Nucleo status (see TrackingStatus), a carrier status code mapped by the connection's status map, or empty to let Nucleo infer it from description.

    Example: delivered
  • descriptionstring

    Event text (stored up to 500 characters).

    Example: Delivered to recipient
  • occurred_atstring (date-time)

    When the event happened. Defaults to the time of receipt.

  • locationstring

    Where it happened (stored up to 160 characters).

    Example: Milano
  • exception_codestring

    Detail for exception and held.

    One ofaddress_wrongrecipient_absentrefuseddamagedcustomsheld_at_depotat_pickup_pointlostother
QaplaWebhook
  • apiKeystringrequired

    The Qapla' connection's API key in Nucleo.

  • trackingNumberstringrequired
  • datestring

    Event date and time.

    Example: 2026-10-06 09:12:00
  • qaplaStatusIDintegerrequired
  • qaplaStatusstring
  • courierStatusstring
  • placestring
  • statusDetailsarray of object
    Attributes of each item
    • detailstring
  • courierstring
DhlWebhook
  • shipmentsarray of objectrequired
    Attributes of each item
    • idstringrequired

      DHL tracking number.

    • eventsarray of object
      Attributes of each item
      • timestampstring (date-time)
      • statusCodestring
        One ofpre-transittransitdeliveredfailureunknown
      • descriptionstring
      • locationobject
        Child attributes
        • addressobject
          Child attributes
          • addressLocalitystring
          • countryCodestring
    • statusobject

      Latest status, used when events is empty (same shape as an event).

Responses

  • 200Accepted. applied is the number of new events stored.
    Headers
    • X-RateLimit-Limit Requests allowed per minute.
    • X-RateLimit-Remaining Requests left in the current minute.
    • result"OK"required
    • appliedintegerrequired
      min 0
  • 400The body is not a JSON object.
    • result"KO"required
    • errorstringrequired
      One ofunknown connectioninvalid jsonunauthorized
  • 401Wrong or missing signature / key / apiKey.
    • result"KO"required
    • errorstringrequired
      One ofunknown connectioninvalid jsonunauthorized
  • 404No carrier or Qapla' connection with this ID (unknown connection). A non-UUID ID gets the generic route-not-found message.

    One of the following shapes:

    WebhookError
    • result"KO"required
    • errorstringrequired
      One ofunknown connectioninvalid jsonunauthorized
    Message
    • messagestringrequired
  • 429Too many requests from this IP.
    Headers
    • Retry-After Seconds to wait.
    • X-RateLimit-Limit Requests allowed per minute.
    • X-RateLimit-Remaining Requests left in the current minute.
    • X-RateLimit-Reset Unix time when the limit resets.
    • messagestringrequired
Request
curl -X POST https://api-commerce.nucleoplatform.com/api/oms/v1/webhooks/tracking/5f0c7e2a-8b3d-4c1e-9a6f-2d4b8e1c7a35 \
  -H "X-Nucleo-Signature: $NUCLEO_SIGNATURE" \
  -H 'Content-Type: application/json' \
  -d '{
  "events": [
    {
      "tracking_number": "0612345678901",
      "status": "",
      "description": "Consegnata al destinatario",
      "occurred_at": "2026-10-06T11:05:00Z",
      "location": "Milano"
    },
    {
      "tracking_number": "0612345678902",
      "status": "exception",
      "exception_code": "recipient_absent",
      "description": "Recipient not at home, second attempt tomorrow",
      "occurred_at": "2026-10-06T11:20:00Z",
      "location": "Torino"
    }
  ]
}'
Response
{
  "result": "OK",
  "applied": 2
}