Track 360
PricingDocsAPI DocsBlogContactSign inStart free
PricingDocsAPI DocsBlogContactSign in

Guides

  • Introduction
  • Authentication
  • Scopes
  • Requests and responses
  • Pagination
  • Rate limits
  • Idempotency
  • Plans and usage
  • Errors

Objects

  • Shipment object
  • Statuses

Shipments

  • POSTCreate a shipment
  • POSTCreate shipments in bulk
  • GETList shipments
  • GETRetrieve a shipment
  • PATCHUpdate a shipment
  • DELETEDelete a shipment
  • POSTDelete shipments in bulk
  • POSTArchive a shipment
  • POSTRefresh tracking

Tracking

  • GETGet tracking status
  • GETList tracking events
  • GETLook up by tracking number
  • POSTLook up live at the carrier

Returns

  • GETCheck return eligibility
  • POSTCreate a return
  • GETList a shipment’s returns
  • GETList returns
  • GETSummarize returns
  • PATCHUpdate a return’s status

Exceptions

  • GETList exceptions
  • GETSummarize exceptions

Reports

  • GETDashboard totals
  • GETShipments created per day
  • GETDelivery performance
  • GETCarrier performance
  • GETShipment flow
  • GETDelivery trend
  • GETNotification delivery
  • POSTExport a report as CSV

API reference

Build on the shipment tracking API

Create and track shipments, read returns and exceptions, and pull reports from your own systems. This reference covers the 29 endpoints you can call with an API key.

  • JSON over HTTPS
  • Bearer API keys
  • Scoped, per organization
  • Release notes
Base URL
https://track360.tdccommerce.com/api/v1

Introduction

What the API does, its base URL and a first request.

The API lets your systems create and track shipments, read returns and exceptions, and pull reports for your organization. It is a JSON REST API over HTTPS. This reference documents every endpoint you can call with an API key, and only those.

Base URL

Every path in this reference is relative to the versioned root https://track360.tdccommerce.com/api/v1. Requests and responses are JSON (UTF-8) except the CSV export. Timestamps are ISO 8601 in UTC.

Make your first request

Create a key on the Developers page of your dashboard, keep it in an environment variable called API_KEY, and list your shipments:

curl "https://track360.tdccommerce.com/api/v1/shipments?limit=2&status=active" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipments retrieved successfully",
  "data": [
    {
      "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "tracking_number": "1Z999AA10123456784",
      "courier_code": "ups",
      "order_number": "ORD-10045",
      "order_date": null,
      "created_at": "2026-10-20T14:32:08.417Z",
      "update_at": "2026-10-20T14:32:08.417Z",
      "delivery_status": "pending",
      "archived": "tracking",
      "updating": true,
      "source": "API",
      "destination_country": "US",
      "destination_state": null,
      "destination_city": null,
      "origin_country": null,
      "origin_state": null,
      "origin_city": null,
      "tracking_postal_code": null,
      "tracking_ship_date": null,
      "tracking_destination_country": "US",
      "tracking_origin_country": null,
      "tracking_key": null,
      "tracking_courier_account": null,
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]",
      "customer_sms": null,
      "recipient_postcode": "78701",
      "order_id": "ORD-10045",
      "title": null,
      "logistics_channel": "UPS Ground",
      "note": "Leave at front desk",
      "label": null,
      "signed_by": null,
      "service_code": "UPS Ground",
      "weight": null,
      "weight_kg": null,
      "product_type": null,
      "pieces": null,
      "dimension": null,
      "previously": null,
      "destination_track_number": null,
      "exchange_number": null,
      "scheduled_delivery_date": null,
      "scheduled_address": null,
      "substatus": null,
      "status_info": null,
      "latest_event": null,
      "latest_checkpoint_time": null,
      "transit_time": 1,
      "origin_info": {
        "courier_code": "ups",
        "courier_phone": "1.800.742.5877",
        "weblink": "https://www.ups.com/",
        "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
        "reference_number": "ups",
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "destination_info": {
        "courier_code": null,
        "courier_phone": null,
        "weblink": null,
        "tracking_link": null,
        "reference_number": null,
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
      "trackingNumber": "1Z999AA10123456784",
      "normalizedTrackingNumber": "1Z999AA10123456784",
      "carrier": {
        "id": "carr_ups",
        "code": "ups",
        "name": "United Parcel Service (UPS)"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "status": "active",
      "currentTrackingStatus": "pending",
      "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
      "service": "UPS Ground",
      "externalId": null,
      "externalOrderId": "ORD-10045",
      "originPostalCode": null,
      "destinationPostalCode": "78701",
      "metadata": {
        "warehouse": "AUS-1",
        "note": "Leave at front desk",
        "customer_name": "Jane Doe",
        "customer_email": "[email protected]"
      },
      "createdAt": "2026-10-20T14:32:08.417Z",
      "updatedAt": "2026-10-20T14:32:08.417Z",
      "archivedAt": null
    },
    {
      "id": "c91d0a73-5be2-4a18-8d64-0f7e3b2c1a59",
      "tracking_number": "794644790138",
      "courier_code": "fedex",
      "order_number": "ORD-10046",
      "order_date": null,
      "created_at": "2026-10-20T13:10:44.002Z",
      "update_at": "2026-10-20T13:10:44.002Z",
      "delivery_status": "pending",
      "archived": "tracking",
      "updating": true,
      "source": "API",
      "destination_country": "US",
      "destination_state": null,
      "destination_city": null,
      "origin_country": null,
      "origin_state": null,
      "origin_city": null,
      "tracking_postal_code": null,
      "tracking_ship_date": null,
      "tracking_destination_country": "US",
      "tracking_origin_country": null,
      "tracking_key": null,
      "tracking_courier_account": null,
      "customer_name": "Sam Rivera",
      "customer_email": "[email protected]",
      "customer_sms": null,
      "recipient_postcode": "10001",
      "order_id": "ORD-10046",
      "title": null,
      "logistics_channel": "FedEx Ground",
      "note": null,
      "label": null,
      "signed_by": null,
      "service_code": "FedEx Ground",
      "weight": null,
      "weight_kg": null,
      "product_type": null,
      "pieces": null,
      "dimension": null,
      "previously": null,
      "destination_track_number": null,
      "exchange_number": null,
      "scheduled_delivery_date": null,
      "scheduled_address": null,
      "substatus": null,
      "status_info": null,
      "latest_event": null,
      "latest_checkpoint_time": null,
      "transit_time": 1,
      "origin_info": {
        "courier_code": "fedex",
        "courier_phone": "1.800.247.4747",
        "weblink": "https://www.fedex.com/",
        "tracking_link": "https://www.fedex.com/fedextrack/?trknbr=794644790138",
        "reference_number": "fedex",
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "destination_info": {
        "courier_code": null,
        "courier_phone": null,
        "weblink": null,
        "tracking_link": null,
        "reference_number": null,
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
      "trackingNumber": "794644790138",
      "normalizedTrackingNumber": "794644790138",
      "carrier": {
        "id": "carr_fedex",
        "code": "fedex",
        "name": "FedEx"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "status": "active",
      "currentTrackingStatus": "pending",
      "currentTrackingStatusAt": "2026-10-20T13:10:44.001Z",
      "service": "FedEx Ground",
      "externalId": null,
      "externalOrderId": "ORD-10046",
      "originPostalCode": null,
      "destinationPostalCode": "10001",
      "metadata": {
        "customer_name": "Sam Rivera",
        "customer_email": "[email protected]"
      },
      "createdAt": "2026-10-20T13:10:44.002Z",
      "updatedAt": "2026-10-20T13:10:44.002Z",
      "archivedAt": null
    }
  ],
  "pagination": {
    "total": 42,
    "page": 1,
    "limit": 2,
    "totalPages": 21,
    "hasNextPage": true,
    "hasPrevPage": false
  }
}

You get back a JSON envelope with your shipments in data and paging details in pagination. If you see 401, check the key; if you see 403, read the code and Authentication.

Authentication

Authenticate with a secret API key sent as a Bearer token.

Send your API key in the Authorization header of every request:

Header
Authorization: Bearer $API_KEY

A key looks like sk_live_XXXXXXXX_…: the prefix sk_live_, eight characters that identify the key, and a long secret. Bearer is case-sensitive, and no other way of sending the key is accepted.

A key is shown once, when you create it. Only a hash is stored, so a lost key cannot be recovered: create a new one. Keep keys on your servers, never in browser code, mobile apps or public repositories, and revoke a leaked key immediately.

Keys and limits

  • API access must be included in your plan.
  • An organization can have up to four active keys, fewer if its plan allows fewer. When a plan is downgraded, only the oldest keys up to the new limit keep working.
  • A key can expire on a date you choose. Keys created by a member are revoked automatically when that member leaves the organization or loses the developer role.
  • Rotating a key gives you a new one and keeps the old one working for a grace period (1 to 168 hours, 24 by default) so you can deploy without downtime.

When authentication fails

StatusCodeMeaning
401(none)The key is missing, malformed, wrong, expired or revoked. These cases are deliberately indistinguishable.
403API_KEY_SCOPE_REQUIREDThe key is valid but lacks a scope this endpoint needs. The message names it.
403API_KEY_ACCESS_NOT_ALLOWEDThis endpoint does not accept API keys. Only the endpoints in this reference do.
403API_ACCESS_NOT_IN_PLANThe organization’s plan does not include API access, or it has no active plan. Plan changes can take up to a minute to apply.
403ORGANIZATION_SUSPENDEDThe organization is suspended. Contact support.

Scopes

Each key carries the scopes it may use. Grant only what an integration needs.

Every endpoint lists the scope it requires. A request with a key that lacks it is refused with 403 API_KEY_SCOPE_REQUIRED before anything else happens.

ScopeAllows
shipments:readRead shipments, their status, tracking events, and look up tracking numbers.
shipments:writeCreate, update, archive, delete and refresh shipments.
exceptions:readRead delivery exceptions.
analytics:readRead reports and export them.
returns:readRead returns and check return eligibility.
returns:writeCreate returns and move them through their lifecycle.
*Every scope above. It cannot reach anything an API key is not allowed to call.

Prefer narrow scopes: a reporting job needs only analytics:read, a storefront integration usually shipments:read and shipments:write.

Requests and responses

Content types, the response envelope and how ids and timestamps look.

Requests

  • Send bodies as JSON with Content-Type: application/json, up to 1 MiB (larger bodies get 413, other content types 415, invalid JSON 400).
  • Send no Content-Type header and no body on requests that take none (DELETE, archive, retrack). A JSON content type with an empty body is rejected with 400 FST_ERR_CTP_EMPTY_JSON_BODY.
  • URL-encode ids and tracking numbers you put in a path.
  • Fields an endpoint does not list are ignored, except on the two Returns write endpoints, which reject them.

Responses

Envelope
{
  "statusCode": 200,
  "message": "Shipments retrieved successfully",
  "data": [ … ],
  "pagination": { … }
}
  • data holds the result: an object, or an array on list endpoints, which also return pagination. message is for people: do not parse it.
  • Timestamps are ISO 8601 strings in UTC. Ids are strings.
  • Treat responses as open: ignore fields you do not recognize.
  • You only ever see your own organization’s data. Another organization’s id answers 404 exactly like an id that does not exist.

Pagination

List endpoints return one page at a time.

List endpoints (shipments, tracking events, exceptions, returns) take page and limit and answer with a pagination object next to data.

pagination
{
  "total": 42,
  "page": 1,
  "limit": 20,
  "totalPages": 3,
  "hasNextPage": true,
  "hasPrevPage": false
}
  • page starts at 1. limit is 1 to 100 and defaults to 20.
  • A page past the end returns an empty data array. A value out of range, or not a number, is a 400.
  • totalPages is at least 1, even when there is nothing to list.
  • Keep requesting page + 1 while hasNextPage is true.

Rate limits

How many requests you can make, and how to back off.

All requests made with your organization’s API keys share one limit, whichever key they use. It is separate from the limit on your team’s use of the dashboard, and it depends on your plan (see pricing).

HeaderMeaning
X-RateLimit-LimitRequests allowed per window.
X-RateLimit-RemainingRequests left in the current window.
X-RateLimit-ResetThe length of the window in seconds. It is not a timestamp.
Retry-AfterOn a 429 only: how many seconds to wait. Also the full window length.

Past the limit you get 429 RATE_LIMIT_EXCEEDED. Requests rejected for that reason do not count, but every other response does, including 400, 403 and 404.

Back off when X-RateLimit-Remaining nears zero, wait Retry-After seconds after a 429, and use the bulk endpoints for imports instead of many single calls.

Idempotency

Retry creates safely with an Idempotency-Key.

Creating shipments (one or many) accepts an Idempotency-Key header: a unique string of up to 255 characters that you choose per operation, for example order-10045-create. If a request times out, send it again with the same key and the same body.

SituationResult
Same key, same body, the first request finishedThe stored response is returned again, with the same status (201). Nothing is created twice.
Same key, different body409 IDEMPOTENCY_KEY_MISMATCH. Use a new key for a new operation.
Same key, same body, the first request is still running409 IDEMPOTENCY_IN_PROGRESS. Retry in a moment.
The first attempt failed (for example a 402 or 503)The retry runs again.
  • Keys are remembered for 24 hours and belong to your organization.
  • For bulk create, row i is stored under <key>_row_<i>, so a retry replays rows that finished and re-runs the ones that failed. Conflicts show up as failed rows, never as a 409.
  • A tracking number you already track is never created twice, with or without a key.

Plans and usage

What your plan has to include, and what counts against your allowance.

  • API access is a plan feature. Without it every request answers 403 API_ACCESS_NOT_IN_PLAN.
  • Creating or bulk-creating shipments, refreshing tracking and live carrier lookups need an active subscription: otherwise 402 ACTIVE_SUBSCRIPTION_REQUIRED.
  • Creating a return needs the Returns feature and exporting a report the Report exports feature: otherwise 402 FEATURE_NOT_IN_PLAN, with the missing feature named in feature.
  • Every newly created shipment uses one unit of your shipment allowance for the billing period. Past it, creating answers 402 SHIPMENT_LIMIT_REACHED. Duplicates and idempotent replays are free; archiving or deleting a shipment does not give its unit back.
  • Reports reach back as far as your plan’s analytics retention; an earlier start is moved forward to it.

The limits of each plan are on the pricing page.

Errors

Every error has an HTTP status and, almost always, a machine-readable code.

Error response
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "trackingNumber: Required",
  "code": "VALIDATION_ERROR",
  "details": [
    { "path": ["trackingNumber"], "message": "Required", "code": "invalid_type" }
  ]
}

Branch on the HTTP status and on code. The wording of message and details[].message can change, and differs between endpoints; details[].path names the offending field, with array positions as numbers. Server errors (5xx) also carry a requestId: quote it when you contact support.

StatusCodeMeaning
400VALIDATION_ERRORInvalid parameters or body. This is a 400, not a 422.
400INVALID_CUSTOMERThe customerId is not one of your customers.
400FST_ERR_CTP_*The body could not be read: invalid JSON, or empty with a JSON content type.
401(none)No valid API key. See Authentication.
402ACTIVE_SUBSCRIPTION_REQUIREDThe organization needs an active subscription.
402SHIPMENT_LIMIT_REACHEDThe plan’s shipment allowance is used up.
402FEATURE_NOT_IN_PLANThe plan lacks a feature this endpoint needs; feature names it.
403API_KEY_SCOPE_REQUIRED · API_KEY_ACCESS_NOT_ALLOWED · API_ACCESS_NOT_IN_PLAN · ORGANIZATION_SUSPENDEDSee Authentication.
404SHIPMENT_NOT_FOUND · RETURN_NOT_FOUND · TRACKING_NUMBER_NOT_FOUNDThe record does not exist in your organization. An unknown URL is a 404 without a code.
409IDEMPOTENCY_KEY_MISMATCH · IDEMPOTENCY_IN_PROGRESSSee Idempotency.
409RETURN_ALREADY_EXISTS · SHIPMENT_NOT_TRACKABLEThe request conflicts with the record’s current state.
413 · 415FST_ERR_CTP_BODY_TOO_LARGE · FST_ERR_CTP_INVALID_MEDIA_TYPEThe body is over 1 MiB, or has a content type other than JSON.
422RETURN_NOT_ELIGIBLE · INVALID_RETURN_TRANSITIONThe request is well-formed but not allowed by the return rules.
429RATE_LIMIT_EXCEEDED · RETRACK_COOLDOWNToo many requests, or this shipment was just refreshed. See Rate limits.
500INTERNAL_ERRORSomething went wrong on our side. Retry; if it persists, send the requestId.
503BILLING_SYNC_PENDING · SHIPMENT_QUOTA_BUSY · QUEUE_UNAVAILABLE · SERVICE_UNAVAILABLETemporarily unavailable. Wait for the Retry-After header (5 seconds) and retry.

Retry 429 and 5xx responses with exponential backoff, and 409 IDEMPOTENCY_IN_PROGRESS after a moment. Other 4xx responses will not succeed until you change the request.

Shipment object

One parcel and everything known about it. Create, retrieve, list, update and archive all return it.

Shipment · 200 OK
{
  "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
  "tracking_number": "1Z999AA10123456784",
  "courier_code": "ups",
  "order_number": "ORD-10045",
  "order_date": null,
  "created_at": "2026-10-20T14:32:08.417Z",
  "update_at": "2026-10-20T09:15:04.000Z",
  "delivery_status": "transit",
  "archived": "tracking",
  "updating": true,
  "source": "API",
  "destination_country": "US",
  "destination_state": null,
  "destination_city": null,
  "origin_country": null,
  "origin_state": null,
  "origin_city": null,
  "tracking_postal_code": null,
  "tracking_ship_date": null,
  "tracking_destination_country": "US",
  "tracking_origin_country": null,
  "tracking_key": null,
  "tracking_courier_account": null,
  "customer_name": "Jane Doe",
  "customer_email": "[email protected]",
  "customer_sms": null,
  "recipient_postcode": "78701",
  "order_id": "ORD-10045",
  "title": null,
  "logistics_channel": "UPS Ground",
  "note": "Leave at front desk",
  "label": null,
  "signed_by": null,
  "service_code": "UPS Ground",
  "weight": null,
  "weight_kg": null,
  "product_type": null,
  "pieces": null,
  "dimension": null,
  "previously": null,
  "destination_track_number": null,
  "exchange_number": null,
  "scheduled_delivery_date": null,
  "scheduled_address": null,
  "substatus": "transit001",
  "status_info": null,
  "latest_event": "Departed from Facility,Louisville KY,2026-10-20 09:15:00",
  "latest_checkpoint_time": "2026-10-20T09:15:00.000Z",
  "transit_time": 1,
  "origin_info": {
    "courier_code": "ups",
    "courier_phone": "1.800.742.5877",
    "weblink": "https://www.ups.com/",
    "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
    "reference_number": "ups",
    "milestone_date": {
      "inforeceived_date": "2026-10-19T18:05:00.000Z",
      "pickup_date": "2026-10-19T21:40:00.000Z",
      "outfordelivery_date": null,
      "delivery_date": null,
      "returning_date": null,
      "returned_date": null
    },
    "pickup_date": "2026-10-19T21:40:00.000Z",
    "departed_airport_date": null,
    "arrived_abroad_date": null,
    "customs_received_date": null,
    "trackinfo": [
      {
        "checkpoint_date": "2026-10-20T09:15:00.000Z",
        "checkpoint_delivery_status": "transit",
        "checkpoint_delivery_substatus": "transit001",
        "tracking_detail": "Departed from Facility",
        "location": "Louisville KY",
        "country_iso2": "US",
        "state": "KY",
        "city": "Louisville",
        "zip": null,
        "raw_status": "Departed from Facility"
      },
      {
        "checkpoint_date": "2026-10-19T21:40:00.000Z",
        "checkpoint_delivery_status": "pickup",
        "checkpoint_delivery_substatus": "pickup001",
        "tracking_detail": "Picked up by carrier",
        "location": "Austin TX",
        "country_iso2": "US",
        "state": "TX",
        "city": "Austin",
        "zip": null,
        "raw_status": "Pickup Scan"
      },
      {
        "checkpoint_date": "2026-10-19T18:05:00.000Z",
        "checkpoint_delivery_status": "inforeceived",
        "checkpoint_delivery_substatus": "inforeceived001",
        "tracking_detail": "Shipper created a label, UPS has not received the package yet",
        "location": "",
        "country_iso2": null,
        "state": null,
        "city": null,
        "zip": null,
        "raw_status": "Order Processed: Ready for UPS"
      }
    ]
  },
  "destination_info": {
    "courier_code": null,
    "courier_phone": null,
    "weblink": null,
    "tracking_link": null,
    "reference_number": null,
    "milestone_date": {
      "inforeceived_date": null,
      "pickup_date": null,
      "outfordelivery_date": null,
      "delivery_date": null,
      "returning_date": null,
      "returned_date": null
    },
    "pickup_date": null,
    "departed_airport_date": null,
    "arrived_abroad_date": null,
    "customs_received_date": null,
    "trackinfo": []
  },
  "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
  "trackingNumber": "1Z999AA10123456784",
  "normalizedTrackingNumber": "1Z999AA10123456784",
  "carrier": {
    "id": "carr_ups",
    "code": "ups",
    "name": "United Parcel Service (UPS)"
  },
  "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
  "status": "active",
  "currentTrackingStatus": "in_transit",
  "currentTrackingStatusAt": "2026-10-20T09:15:00.000Z",
  "service": "UPS Ground",
  "externalId": null,
  "externalOrderId": "ORD-10045",
  "originPostalCode": null,
  "destinationPostalCode": "78701",
  "metadata": {
    "warehouse": "AUS-1",
    "note": "Leave at front desk",
    "customer_name": "Jane Doe",
    "customer_email": "[email protected]"
  },
  "createdAt": "2026-10-20T14:32:08.417Z",
  "updatedAt": "2026-10-20T09:15:04.000Z",
  "archivedAt": null
}

The object carries the same record twice: the detailed format (snake_case) and a typed copy in camelCase at the end. Both are always present. Many detailed fields (weight_kg, title, destination_city, …) are filled from the same-named key of the metadata you send, so you can use metadata to carry your own values through.

Identity and status

  • idstring

    Unique shipment id (UUID). Use it in every /shipments/:id path.

  • tracking_numberstring

    The tracking number exactly as you sent it. normalizedTrackingNumber is the form used for matching.

  • courier_codestring

    Lower-case carrier code such as ups. unknown when the shipment was created without a carrier.

  • order_numberstring | null

    Your order reference: externalOrderId, else externalId.

  • order_idstring | null

    Same value as order_number.

  • order_datestring | null

    Taken from metadata.order_date.

  • created_atstring

    ISO 8601 UTC timestamp.

  • update_atstring

    ISO 8601 UTC timestamp of the last change.

  • delivery_statusstring

    Where the parcel is, as one of the public statuses: pending, inforeceived, pickup, transit, outfordelivery, delivered, exception, …

  • substatusstring | null

    <delivery_status>001 once the shipment has a checkpoint, otherwise null. metadata.substatus overrides it.

  • status_infostring | null

    Free text from metadata.status_info.

  • archivedstring

    tracking or archived.

  • updatingboolean

    true while the shipment is active and has not reached delivered, cancelled or returned.

  • sourcestring

    API unless metadata.source says otherwise.

Customer and route

  • customer_namestring | null

    From the linked customer, else metadata.customer_name.

  • customer_emailstring | null

    From the linked customer, else metadata.customer_email.

  • customer_smsstring | null

    Customer phone number.

  • recipient_postcodestring | null

    Destination postal code.

  • origin_countrystring | null

    As sent in originCountry, else metadata.origin_country.

  • origin_statestring | null

    From metadata.origin_state.

  • origin_citystring | null

    From metadata.origin_city.

  • destination_countrystring | null

    As sent in destinationCountry, else metadata.destination_country.

  • destination_statestring | null

    From metadata.destination_state.

  • destination_citystring | null

    From metadata.destination_city.

  • tracking_postal_codestring | null

    Origin postal code.

  • tracking_ship_datestring | null

    From metadata.tracking_ship_date.

  • tracking_origin_countrystring | null

    The originCountry you sent.

  • tracking_destination_countrystring | null

    The destinationCountry you sent.

  • tracking_keystring | null

    From metadata.tracking_key.

  • tracking_courier_accountstring | null

    Id of the carrier account the shipment is tracked through, when one is used. Otherwise null.

Service and parcel

  • logistics_channelstring | null

    The service name you sent (service), or metadata.logistics_channel.

  • service_codestring | null

    serviceCode, else service, else metadata.service_code.

  • notestring | null

    Free-text note (note, stored in metadata.note).

  • titlestring | null

    From metadata.title.

  • labelstring | null

    From metadata.label.

  • signed_bystring | null

    From metadata.signed_by.

  • weightstring | null

    From metadata.weight.

  • weight_kgnumber | null

    From metadata.weight_kg.

  • product_typestring | null

    From metadata.product_type.

  • piecesnumber | null

    From metadata.pieces.

  • dimensionstring | null

    From metadata.dimension.

  • previouslystring | null

    From metadata.previously.

  • destination_track_numberstring | null

    From metadata.destination_track_number.

  • exchange_numberstring | null

    From metadata.exchange_number.

  • scheduled_delivery_datestring | null

    From metadata.scheduled_delivery_date.

  • scheduled_addressstring | null

    From metadata.scheduled_address.

Progress

  • latest_eventstring | null

    The newest checkpoint as description,location,YYYY-MM-DD HH:mm:ss (UTC). null until a checkpoint exists.

  • latest_checkpoint_timestring | null

    ISO 8601 time of the newest checkpoint.

  • transit_timenumber | null

    Whole calendar days from pickup (or creation) to delivery (or the last update), never below 1.

  • origin_infoobject

    Carrier details, milestone dates and, on GET /shipments/:id, the checkpoints. See carrier info.

  • destination_infoobject

    Same shape as origin_info; empty unless metadata.destination_info supplies it.

The same record in camelCase

  • organizationIdstring

    Your organization id.

  • trackingNumberstring

    Same as tracking_number.

  • normalizedTrackingNumberstring

    Upper-cased, with whitespace and hyphens removed. Duplicate detection and the trackingNumber filter use this form.

  • carrierobject

    { id, code, name }. id is carrier_<code> when the carrier has no catalog record of its own.

  • customerIdstring | null

    The linked customer, if any.

  • statusstring

    active or archived. This is the archive state; where the parcel is lives in currentTrackingStatus.

  • currentTrackingStatusstring

    One of the tracking statuses, e.g. in_transit.

  • currentTrackingStatusAtstring | null

    When the status last changed.

  • servicestring | null

    The service you sent.

  • externalIdstring | null

    Your id for the shipment.

  • externalOrderIdstring | null

    Your order id.

  • originPostalCodestring | null

    Origin postal code.

  • destinationPostalCodestring | null

    Destination postal code.

  • metadataobject | null

    Your free-form metadata, plus the note and customer_* values the API copies into it.

  • createdAtstring

    Same as created_at.

  • updatedAtstring

    Same as update_at.

  • archivedAtstring | null

    When the shipment was archived.

Carrier info (origin_info, destination_info)

  • courier_codestring | null

    Carrier code.

  • courier_phonestring | null

    Carrier support phone number (known carriers only).

  • weblinkstring | null

    Carrier website (known carriers only).

  • tracking_linkstring | null

    Carrier page for this tracking number (known carriers only).

  • reference_numberstring | null

    The carrier reference this shipment is tracked under.

  • milestone_dateobject

    inforeceived_date, pickup_date, outfordelivery_date, delivery_date, returning_date, returned_date: ISO 8601 or null.

  • pickup_datestring | null

    Same as milestone_date.pickup_date.

  • departed_airport_datestring | null

    From metadata.departed_airport_date.

  • arrived_abroad_datestring | null

    From metadata.arrived_abroad_date.

  • customs_received_datestring | null

    From metadata.customs_received_date.

  • trackinfoobject[]

    Checkpoints, newest first. Filled on GET /shipments/:id; an empty array everywhere else (use List tracking events to page through them).

Checkpoint (items of trackinfo)

  • checkpoint_datestring

    ISO 8601 time of the scan.

  • checkpoint_delivery_statusstring

    Public status at that scan, e.g. transit.

  • checkpoint_delivery_substatusstring

    <status>001, or the substatus the provider reported.

  • tracking_detailstring

    What the carrier said happened.

  • locationstring

    City, state and postal code joined by spaces; the country code when none of those is known; otherwise empty.

  • country_iso2string | null

    Country code.

  • statestring | null

    State or region.

  • citystring | null

    City.

  • zipstring | null

    Postal code.

  • raw_statusstring | null

    The carrier’s own status text.

Statuses

The tracking statuses a shipment and its events can have.

Where a parcel is lives in currentTrackingStatus (and normalizedStatus on tracking events), and is the value the currentTrackingStatus filter takes. delivery_status on a shipment shows the same state under the name used by the detailed format. Shipments in a final status stop being tracked and cannot be refreshed.

currentTrackingStatusdelivery_statusMeaning
pendingpendingCreated; the carrier has not reported anything yet.
unknownunknownThe carrier’s status could not be interpreted.
label_createdinforeceivedA label exists; the carrier does not have the parcel yet.
pre_transitinforeceivedThe carrier has the shipment details but has not scanned the parcel.
picked_uppickupThe carrier has collected the parcel.
in_transittransitMoving through the carrier’s network.
out_for_deliveryoutfordeliveryOn the vehicle for final delivery.
delivereddeliveredDelivered. Final.
exceptionexceptionThe carrier reported a problem such as a delay, damage or an address issue.
failedundeliveredA delivery attempt failed.
available_for_pickupavailable_for_pickupWaiting for the recipient at a pickup point.
return_to_senderreturntosenderOn its way back to the sender. Final.
returnedreturnedBack with the sender. Final.
cancelledcancelledThe shipment was cancelled. Final.

A shipment’s status is something else: its archive state, active or archived. The live carrier lookup reports statuses in UPPER_CASE; see Look up live at the carrier.

Shipments

Create, read, update, archive and delete the parcels you track.

Create a shipment

Start tracking a parcel. Tracking begins right after creation and updates arrive over time.

POST/shipments
shipments:writeNeeds an active subscription
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H 'Idempotency-Key: order-10045-create' \
  -d '{
  "trackingNumber": "1Z999AA10123456784",
  "carrierCode": "ups",
  "externalOrderId": "ORD-10045",
  "customerName": "Jane Doe",
  "customerEmail": "[email protected]",
  "service": "UPS Ground",
  "note": "Leave at front desk",
  "destinationCountry": "US",
  "destinationPostalCode": "78701",
  "metadata": {
    "warehouse": "AUS-1"
  }
}'
Response · 201 Created
{
  "statusCode": 201,
  "message": "Shipment created successfully",
  "data": {
    "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "tracking_number": "1Z999AA10123456784",
    "courier_code": "ups",
    "order_number": "ORD-10045",
    "order_date": null,
    "created_at": "2026-10-20T14:32:08.417Z",
    "update_at": "2026-10-20T14:32:08.417Z",
    "delivery_status": "pending",
    "archived": "tracking",
    "updating": true,
    "source": "API",
    "destination_country": "US",
    "destination_state": null,
    "destination_city": null,
    "origin_country": null,
    "origin_state": null,
    "origin_city": null,
    "tracking_postal_code": null,
    "tracking_ship_date": null,
    "tracking_destination_country": "US",
    "tracking_origin_country": null,
    "tracking_key": null,
    "tracking_courier_account": null,
    "customer_name": "Jane Doe",
    "customer_email": "[email protected]",
    "customer_sms": null,
    "recipient_postcode": "78701",
    "order_id": "ORD-10045",
    "title": null,
    "logistics_channel": "UPS Ground",
    "note": "Leave at front desk",
    "label": null,
    "signed_by": null,
    "service_code": "UPS Ground",
    "weight": null,
    "weight_kg": null,
    "product_type": null,
    "pieces": null,
    "dimension": null,
    "previously": null,
    "destination_track_number": null,
    "exchange_number": null,
    "scheduled_delivery_date": null,
    "scheduled_address": null,
    "substatus": null,
    "status_info": null,
    "latest_event": null,
    "latest_checkpoint_time": null,
    "transit_time": 1,
    "origin_info": {
      "courier_code": "ups",
      "courier_phone": "1.800.742.5877",
      "weblink": "https://www.ups.com/",
      "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
      "reference_number": "ups",
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "destination_info": {
      "courier_code": null,
      "courier_phone": null,
      "weblink": null,
      "tracking_link": null,
      "reference_number": null,
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
    "trackingNumber": "1Z999AA10123456784",
    "normalizedTrackingNumber": "1Z999AA10123456784",
    "carrier": {
      "id": "carr_ups",
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "status": "active",
    "currentTrackingStatus": "pending",
    "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
    "service": "UPS Ground",
    "externalId": null,
    "externalOrderId": "ORD-10045",
    "originPostalCode": null,
    "destinationPostalCode": "78701",
    "metadata": {
      "warehouse": "AUS-1",
      "note": "Leave at front desk",
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]"
    },
    "createdAt": "2026-10-20T14:32:08.417Z",
    "updatedAt": "2026-10-20T14:32:08.417Z",
    "archivedAt": null
  }
}

Request headers

  • Idempotency-Keystring

    Optional, up to 255 characters. Makes the request safe to retry; see Idempotency.

Request body (JSON)

  • trackingNumberstringrequired

    1 to 128 characters, at least one of them other than a space or hyphen. Stored as you send it; matched ignoring case, spaces and hyphens, so 1z999aa1 0123456784 and 1Z999AA10123456784 are the same shipment.

  • carrierCodestring

    Up to 64 characters, e.g. ups, fedex, usps, dhl. Optional. The code is not checked against a list: one we do not recognize is accepted and tracked through a fallback provider, so check the spelling. Wins over carrierId when both are sent.

  • carrierIdstring

    Up to 64 characters. A carrier record id (carrier.id in a response). Used only when carrierCode is omitted.

  • customerIdstring

    Up to 64 characters. An existing customer of your organization (customerId in a response); another organization's id is rejected with INVALID_CUSTOMER. Usually unnecessary: send customerEmail, customerName or customerPhone and the customer is matched by email or created.

  • customerNamestring

    Up to 255 characters, trimmed.

  • customerEmailstring

    A valid email, up to 255 characters. An empty string is accepted.

  • customerPhonestring

    Up to 64 characters, trimmed.

  • notestring

    Up to 1,000 characters, trimmed. Also copied into metadata.note.

  • servicestring

    Up to 128 characters, e.g. UPS Ground.

  • serviceCodestring

    Up to 128 characters.

  • externalIdstring

    Your own id for the shipment, up to 128 characters.

  • externalOrderIdstring

    Your order id, up to 128 characters. GET /shipments can filter and search by it.

  • originCountrystring

    Up to 128 characters. Free text; ISO 3166-1 alpha-2 such as US is recommended.

  • destinationCountrystring

    Up to 128 characters, same format as originCountry.

  • originPostalCodestring

    Up to 64 characters.

  • destinationPostalCodestring

    Up to 64 characters.

  • metadataobject

    Free-form JSON object, up to 16 KB serialized. Keys such as weight_kg, title or destination_city also fill the matching top-level field of the Shipment.

Response

201
The new Shipment.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

  • 400
    INVALID_CUSTOMER

    customerId does not belong to your organization.

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

  • 402
    SHIPMENT_LIMIT_REACHED

    You have used every shipment your plan includes for this billing period.

  • 409
    IDEMPOTENCY_KEY_MISMATCH

    The Idempotency-Key was already used with a different body.

  • 409
    IDEMPOTENCY_IN_PROGRESS

    A request with the same key and body is still being processed.

  • 503
    BILLING_SYNC_PENDING

    Your billing period is being renewed. Retry after the Retry-After header (5 seconds).

  • 503
    SHIPMENT_QUOTA_BUSY

    Too many shipments are being created at once for your organization. Retry after the Retry-After header (5 seconds).

Plus the general errors every request can get (401, 403, 429, 5xx).

Sending a tracking number you already track (same carrier) is not an error: you get the existing shipment back with status 201. Nothing is created, counted against your allowance or announced, and the new body is ignored. That also holds for an archived shipment.

Each newly created shipment uses one unit of your plan’s shipment allowance. Archiving or deleting it does not give the unit back.

A shipment created without carrierCode or carrierId shows carrier.code unknown until tracking identifies the carrier.

Create shipments in bulk

Create up to 100 shipments in one request. Each row is processed on its own and reported in results.

POST/shipments/bulk
shipments:writeNeeds an active subscription
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments/bulk" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H 'Idempotency-Key: import-2026-10-20' \
  -d '{
  "shipments": [
    {
      "trackingNumber": "1Z999AA10123456784",
      "carrierCode": "ups",
      "externalOrderId": "ORD-10045"
    },
    {
      "trackingNumber": "794644790138",
      "carrierCode": "fedex",
      "externalOrderId": "ORD-10046"
    }
  ]
}'
Response · 201 Created
{
  "statusCode": 201,
  "message": "Bulk shipment processing completed",
  "data": {
    "total": 2,
    "createdCount": 1,
    "failedCount": 1,
    "results": [
      {
        "index": 0,
        "trackingNumber": "1Z999AA10123456784",
        "status": "created",
        "data": {
          "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
          "tracking_number": "1Z999AA10123456784",
          "courier_code": "ups",
          "order_number": "ORD-10045",
          "order_date": null,
          "created_at": "2026-10-20T14:32:08.417Z",
          "update_at": "2026-10-20T14:32:08.417Z",
          "delivery_status": "pending",
          "archived": "tracking",
          "updating": true,
          "source": "API",
          "destination_country": "US",
          "destination_state": null,
          "destination_city": null,
          "origin_country": null,
          "origin_state": null,
          "origin_city": null,
          "tracking_postal_code": null,
          "tracking_ship_date": null,
          "tracking_destination_country": "US",
          "tracking_origin_country": null,
          "tracking_key": null,
          "tracking_courier_account": null,
          "customer_name": "Jane Doe",
          "customer_email": "[email protected]",
          "customer_sms": null,
          "recipient_postcode": "78701",
          "order_id": "ORD-10045",
          "title": null,
          "logistics_channel": "UPS Ground",
          "note": "Leave at front desk",
          "label": null,
          "signed_by": null,
          "service_code": "UPS Ground",
          "weight": null,
          "weight_kg": null,
          "product_type": null,
          "pieces": null,
          "dimension": null,
          "previously": null,
          "destination_track_number": null,
          "exchange_number": null,
          "scheduled_delivery_date": null,
          "scheduled_address": null,
          "substatus": null,
          "status_info": null,
          "latest_event": null,
          "latest_checkpoint_time": null,
          "transit_time": 1,
          "origin_info": {
            "courier_code": "ups",
            "courier_phone": "1.800.742.5877",
            "weblink": "https://www.ups.com/",
            "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
            "reference_number": "ups",
            "milestone_date": {
              "inforeceived_date": null,
              "pickup_date": null,
              "outfordelivery_date": null,
              "delivery_date": null,
              "returning_date": null,
              "returned_date": null
            },
            "pickup_date": null,
            "departed_airport_date": null,
            "arrived_abroad_date": null,
            "customs_received_date": null,
            "trackinfo": []
          },
          "destination_info": {
            "courier_code": null,
            "courier_phone": null,
            "weblink": null,
            "tracking_link": null,
            "reference_number": null,
            "milestone_date": {
              "inforeceived_date": null,
              "pickup_date": null,
              "outfordelivery_date": null,
              "delivery_date": null,
              "returning_date": null,
              "returned_date": null
            },
            "pickup_date": null,
            "departed_airport_date": null,
            "arrived_abroad_date": null,
            "customs_received_date": null,
            "trackinfo": []
          },
          "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
          "trackingNumber": "1Z999AA10123456784",
          "normalizedTrackingNumber": "1Z999AA10123456784",
          "carrier": {
            "id": "carr_ups",
            "code": "ups",
            "name": "United Parcel Service (UPS)"
          },
          "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
          "status": "active",
          "currentTrackingStatus": "pending",
          "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
          "service": "UPS Ground",
          "externalId": null,
          "externalOrderId": "ORD-10045",
          "originPostalCode": null,
          "destinationPostalCode": "78701",
          "metadata": {
            "warehouse": "AUS-1",
            "note": "Leave at front desk",
            "customer_name": "Jane Doe",
            "customer_email": "[email protected]"
          },
          "createdAt": "2026-10-20T14:32:08.417Z",
          "updatedAt": "2026-10-20T14:32:08.417Z",
          "archivedAt": null
        }
      },
      {
        "index": 1,
        "trackingNumber": "794644790138",
        "status": "limit_reached",
        "error": "You have used all shipments included in your plan for this billing period. Upgrade your plan or contact us for additional shipments."
      }
    ]
  }
}

Request headers

  • Idempotency-Keystring

    Optional, up to 255 characters. Makes the request safe to retry; see Idempotency.

Request body (JSON)

  • shipmentsobject[]required

    1 to 100 items. Each item takes the same fields as Create a shipment.

Response

201
A summary and one result per row, in request order.

Errors

  • 400
    VALIDATION_ERROR

    The body is invalid, or any single row is. Rows are checked before anything is created, so one bad row rejects the whole request; details[].path points at it, e.g. shipments.1.trackingNumber.

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

Plus the general errors every request can get (401, 403, 429, 5xx).

The response is 201 even if every row failed. Check failedCount and each row’s status: created, failed or limit_reached. A failed row carries a plain-text error, not a code, and one failing row does not stop the others.

A tracking number you already track counts as created and returns the existing shipment, exactly as in Create a shipment.

With an Idempotency-Key, row i is stored under <key>_row_<i>, so retrying the same request replays finished rows and re-runs failed ones. Keys can be at most 248 characters here. Row statuses: created, failed, limit_reached.

List shipments

A page of your shipments, newest first by default.

GET/shipments
shipments:read
curl "https://track360.tdccommerce.com/api/v1/shipments?limit=2&status=active" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipments retrieved successfully",
  "data": [
    {
      "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "tracking_number": "1Z999AA10123456784",
      "courier_code": "ups",
      "order_number": "ORD-10045",
      "order_date": null,
      "created_at": "2026-10-20T14:32:08.417Z",
      "update_at": "2026-10-20T14:32:08.417Z",
      "delivery_status": "pending",
      "archived": "tracking",
      "updating": true,
      "source": "API",
      "destination_country": "US",
      "destination_state": null,
      "destination_city": null,
      "origin_country": null,
      "origin_state": null,
      "origin_city": null,
      "tracking_postal_code": null,
      "tracking_ship_date": null,
      "tracking_destination_country": "US",
      "tracking_origin_country": null,
      "tracking_key": null,
      "tracking_courier_account": null,
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]",
      "customer_sms": null,
      "recipient_postcode": "78701",
      "order_id": "ORD-10045",
      "title": null,
      "logistics_channel": "UPS Ground",
      "note": "Leave at front desk",
      "label": null,
      "signed_by": null,
      "service_code": "UPS Ground",
      "weight": null,
      "weight_kg": null,
      "product_type": null,
      "pieces": null,
      "dimension": null,
      "previously": null,
      "destination_track_number": null,
      "exchange_number": null,
      "scheduled_delivery_date": null,
      "scheduled_address": null,
      "substatus": null,
      "status_info": null,
      "latest_event": null,
      "latest_checkpoint_time": null,
      "transit_time": 1,
      "origin_info": {
        "courier_code": "ups",
        "courier_phone": "1.800.742.5877",
        "weblink": "https://www.ups.com/",
        "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
        "reference_number": "ups",
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "destination_info": {
        "courier_code": null,
        "courier_phone": null,
        "weblink": null,
        "tracking_link": null,
        "reference_number": null,
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
      "trackingNumber": "1Z999AA10123456784",
      "normalizedTrackingNumber": "1Z999AA10123456784",
      "carrier": {
        "id": "carr_ups",
        "code": "ups",
        "name": "United Parcel Service (UPS)"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "status": "active",
      "currentTrackingStatus": "pending",
      "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
      "service": "UPS Ground",
      "externalId": null,
      "externalOrderId": "ORD-10045",
      "originPostalCode": null,
      "destinationPostalCode": "78701",
      "metadata": {
        "warehouse": "AUS-1",
        "note": "Leave at front desk",
        "customer_name": "Jane Doe",
        "customer_email": "[email protected]"
      },
      "createdAt": "2026-10-20T14:32:08.417Z",
      "updatedAt": "2026-10-20T14:32:08.417Z",
      "archivedAt": null
    },
    {
      "id": "c91d0a73-5be2-4a18-8d64-0f7e3b2c1a59",
      "tracking_number": "794644790138",
      "courier_code": "fedex",
      "order_number": "ORD-10046",
      "order_date": null,
      "created_at": "2026-10-20T13:10:44.002Z",
      "update_at": "2026-10-20T13:10:44.002Z",
      "delivery_status": "pending",
      "archived": "tracking",
      "updating": true,
      "source": "API",
      "destination_country": "US",
      "destination_state": null,
      "destination_city": null,
      "origin_country": null,
      "origin_state": null,
      "origin_city": null,
      "tracking_postal_code": null,
      "tracking_ship_date": null,
      "tracking_destination_country": "US",
      "tracking_origin_country": null,
      "tracking_key": null,
      "tracking_courier_account": null,
      "customer_name": "Sam Rivera",
      "customer_email": "[email protected]",
      "customer_sms": null,
      "recipient_postcode": "10001",
      "order_id": "ORD-10046",
      "title": null,
      "logistics_channel": "FedEx Ground",
      "note": null,
      "label": null,
      "signed_by": null,
      "service_code": "FedEx Ground",
      "weight": null,
      "weight_kg": null,
      "product_type": null,
      "pieces": null,
      "dimension": null,
      "previously": null,
      "destination_track_number": null,
      "exchange_number": null,
      "scheduled_delivery_date": null,
      "scheduled_address": null,
      "substatus": null,
      "status_info": null,
      "latest_event": null,
      "latest_checkpoint_time": null,
      "transit_time": 1,
      "origin_info": {
        "courier_code": "fedex",
        "courier_phone": "1.800.247.4747",
        "weblink": "https://www.fedex.com/",
        "tracking_link": "https://www.fedex.com/fedextrack/?trknbr=794644790138",
        "reference_number": "fedex",
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "destination_info": {
        "courier_code": null,
        "courier_phone": null,
        "weblink": null,
        "tracking_link": null,
        "reference_number": null,
        "milestone_date": {
          "inforeceived_date": null,
          "pickup_date": null,
          "outfordelivery_date": null,
          "delivery_date": null,
          "returning_date": null,
          "returned_date": null
        },
        "pickup_date": null,
        "departed_airport_date": null,
        "arrived_abroad_date": null,
        "customs_received_date": null,
        "trackinfo": []
      },
      "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
      "trackingNumber": "794644790138",
      "normalizedTrackingNumber": "794644790138",
      "carrier": {
        "id": "carr_fedex",
        "code": "fedex",
        "name": "FedEx"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "status": "active",
      "currentTrackingStatus": "pending",
      "currentTrackingStatusAt": "2026-10-20T13:10:44.001Z",
      "service": "FedEx Ground",
      "externalId": null,
      "externalOrderId": "ORD-10046",
      "originPostalCode": null,
      "destinationPostalCode": "10001",
      "metadata": {
        "customer_name": "Sam Rivera",
        "customer_email": "[email protected]"
      },
      "createdAt": "2026-10-20T13:10:44.002Z",
      "updatedAt": "2026-10-20T13:10:44.002Z",
      "archivedAt": null
    }
  ],
  "pagination": {
    "total": 42,
    "page": 1,
    "limit": 2,
    "totalPages": 21,
    "hasNextPage": true,
    "hasPrevPage": false
  }
}

Query parameters

  • pageinteger

    Page number, starting at 1.

    Default 1
  • limitinteger

    Items per page, 1 to 100.

    Default 20
  • statusstring

    Archive state. Archived shipments are hidden unless you ask for them.

    One ofactivearchivedDefault active
  • currentTrackingStatusstring

    Only shipments in this tracking status.

    One ofpendingunknownlabel_createdpre_transitpicked_upin_transitout_for_deliverydeliveredexceptionfailedavailable_for_pickupreturn_to_senderreturnedcancelled
  • carrierIdstring

    A carrier record id (carrier.id, e.g. carr_ups), not a carrier code.

  • customerIdstring

    Only shipments linked to this customer.

  • trackingNumberstring

    Exact match, ignoring case, spaces and hyphens.

  • externalIdstring

    Exact match on your shipment id.

  • externalOrderIdstring

    Exact match on your order id.

  • searchstring

    2 to 128 characters. Substring match on the tracking number or the order id.

  • sortBystring

    Sort field. Ties are broken by id.

    One ofcreated_atupdated_atcurrent_tracking_statusDefault created_at
  • sortOrderstring

    Sort direction.

    One ofascdescDefault desc

Response

200
An array of Shipments and a pagination object. Items carry no checkpoints (origin_info.trackinfo is empty); fetch one shipment for those.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

Plus the general errors every request can get (401, 403, 429, 5xx).

Retrieve a shipment

One shipment with its full checkpoint history.

GET/shipments/:id
shipments:read
curl "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment retrieved successfully",
  "data": {
    "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "tracking_number": "1Z999AA10123456784",
    "courier_code": "ups",
    "order_number": "ORD-10045",
    "order_date": null,
    "created_at": "2026-10-20T14:32:08.417Z",
    "update_at": "2026-10-20T09:15:04.000Z",
    "delivery_status": "transit",
    "archived": "tracking",
    "updating": true,
    "source": "API",
    "destination_country": "US",
    "destination_state": null,
    "destination_city": null,
    "origin_country": null,
    "origin_state": null,
    "origin_city": null,
    "tracking_postal_code": null,
    "tracking_ship_date": null,
    "tracking_destination_country": "US",
    "tracking_origin_country": null,
    "tracking_key": null,
    "tracking_courier_account": null,
    "customer_name": "Jane Doe",
    "customer_email": "[email protected]",
    "customer_sms": null,
    "recipient_postcode": "78701",
    "order_id": "ORD-10045",
    "title": null,
    "logistics_channel": "UPS Ground",
    "note": "Leave at front desk",
    "label": null,
    "signed_by": null,
    "service_code": "UPS Ground",
    "weight": null,
    "weight_kg": null,
    "product_type": null,
    "pieces": null,
    "dimension": null,
    "previously": null,
    "destination_track_number": null,
    "exchange_number": null,
    "scheduled_delivery_date": null,
    "scheduled_address": null,
    "substatus": "transit001",
    "status_info": null,
    "latest_event": "Departed from Facility,Louisville KY,2026-10-20 09:15:00",
    "latest_checkpoint_time": "2026-10-20T09:15:00.000Z",
    "transit_time": 1,
    "origin_info": {
      "courier_code": "ups",
      "courier_phone": "1.800.742.5877",
      "weblink": "https://www.ups.com/",
      "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
      "reference_number": "ups",
      "milestone_date": {
        "inforeceived_date": "2026-10-19T18:05:00.000Z",
        "pickup_date": "2026-10-19T21:40:00.000Z",
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": "2026-10-19T21:40:00.000Z",
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": [
        {
          "checkpoint_date": "2026-10-20T09:15:00.000Z",
          "checkpoint_delivery_status": "transit",
          "checkpoint_delivery_substatus": "transit001",
          "tracking_detail": "Departed from Facility",
          "location": "Louisville KY",
          "country_iso2": "US",
          "state": "KY",
          "city": "Louisville",
          "zip": null,
          "raw_status": "Departed from Facility"
        },
        {
          "checkpoint_date": "2026-10-19T21:40:00.000Z",
          "checkpoint_delivery_status": "pickup",
          "checkpoint_delivery_substatus": "pickup001",
          "tracking_detail": "Picked up by carrier",
          "location": "Austin TX",
          "country_iso2": "US",
          "state": "TX",
          "city": "Austin",
          "zip": null,
          "raw_status": "Pickup Scan"
        },
        {
          "checkpoint_date": "2026-10-19T18:05:00.000Z",
          "checkpoint_delivery_status": "inforeceived",
          "checkpoint_delivery_substatus": "inforeceived001",
          "tracking_detail": "Shipper created a label, UPS has not received the package yet",
          "location": "",
          "country_iso2": null,
          "state": null,
          "city": null,
          "zip": null,
          "raw_status": "Order Processed: Ready for UPS"
        }
      ]
    },
    "destination_info": {
      "courier_code": null,
      "courier_phone": null,
      "weblink": null,
      "tracking_link": null,
      "reference_number": null,
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
    "trackingNumber": "1Z999AA10123456784",
    "normalizedTrackingNumber": "1Z999AA10123456784",
    "carrier": {
      "id": "carr_ups",
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "status": "active",
    "currentTrackingStatus": "in_transit",
    "currentTrackingStatusAt": "2026-10-20T09:15:00.000Z",
    "service": "UPS Ground",
    "externalId": null,
    "externalOrderId": "ORD-10045",
    "originPostalCode": null,
    "destinationPostalCode": "78701",
    "metadata": {
      "warehouse": "AUS-1",
      "note": "Leave at front desk",
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]"
    },
    "createdAt": "2026-10-20T14:32:08.417Z",
    "updatedAt": "2026-10-20T09:15:04.000Z",
    "archivedAt": null
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

200
The Shipment. This is the one endpoint that fills origin_info.trackinfo with every checkpoint, newest first.

Errors

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

A shipment from another organization answers exactly like one that does not exist: 404 SHIPMENT_NOT_FOUND.

Update a shipment

Change the customer, order, service, address or metadata of a shipment. Send only the fields you want to change.

PATCH/shipments/:id
shipments:write
curl -X PATCH "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "note": "Leave at front desk",
  "metadata": {
    "fragile": true
  }
}'
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment updated successfully",
  "data": {
    "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "tracking_number": "1Z999AA10123456784",
    "courier_code": "ups",
    "order_number": "ORD-10045",
    "order_date": null,
    "created_at": "2026-10-20T14:32:08.417Z",
    "update_at": "2026-10-20T15:02:41.220Z",
    "delivery_status": "pending",
    "archived": "tracking",
    "updating": true,
    "source": "API",
    "destination_country": "US",
    "destination_state": null,
    "destination_city": null,
    "origin_country": null,
    "origin_state": null,
    "origin_city": null,
    "tracking_postal_code": null,
    "tracking_ship_date": null,
    "tracking_destination_country": "US",
    "tracking_origin_country": null,
    "tracking_key": null,
    "tracking_courier_account": null,
    "customer_name": "Jane Doe",
    "customer_email": "[email protected]",
    "customer_sms": null,
    "recipient_postcode": "78701",
    "order_id": "ORD-10045",
    "title": null,
    "logistics_channel": "UPS Ground",
    "note": "Leave at front desk",
    "label": null,
    "signed_by": null,
    "service_code": "UPS Ground",
    "weight": null,
    "weight_kg": null,
    "product_type": null,
    "pieces": null,
    "dimension": null,
    "previously": null,
    "destination_track_number": null,
    "exchange_number": null,
    "scheduled_delivery_date": null,
    "scheduled_address": null,
    "substatus": null,
    "status_info": null,
    "latest_event": null,
    "latest_checkpoint_time": null,
    "transit_time": 1,
    "origin_info": {
      "courier_code": "ups",
      "courier_phone": "1.800.742.5877",
      "weblink": "https://www.ups.com/",
      "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
      "reference_number": "ups",
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "destination_info": {
      "courier_code": null,
      "courier_phone": null,
      "weblink": null,
      "tracking_link": null,
      "reference_number": null,
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
    "trackingNumber": "1Z999AA10123456784",
    "normalizedTrackingNumber": "1Z999AA10123456784",
    "carrier": {
      "id": "carr_ups",
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "status": "active",
    "currentTrackingStatus": "pending",
    "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
    "service": "UPS Ground",
    "externalId": null,
    "externalOrderId": "ORD-10045",
    "originPostalCode": null,
    "destinationPostalCode": "78701",
    "metadata": {
      "warehouse": "AUS-1",
      "fragile": true,
      "note": "Leave at front desk",
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]"
    },
    "createdAt": "2026-10-20T14:32:08.417Z",
    "updatedAt": "2026-10-20T15:02:41.220Z",
    "archivedAt": null
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Request body (JSON)

  • customerIdstring

    Up to 64 characters. An existing customer of your organization (customerId in a response); another organization's id is rejected with INVALID_CUSTOMER. Usually unnecessary: send customerEmail, customerName or customerPhone and the customer is matched by email or created. Send null to clear it.

  • customerNamestring

    Up to 255 characters, trimmed. Send null to clear it.

  • customerEmailstring

    A valid email, up to 255 characters. An empty string is accepted. Send null to clear it.

  • customerPhonestring

    Up to 64 characters, trimmed. Send null to clear it.

  • notestring

    Up to 1,000 characters, trimmed. Also copied into metadata.note. Send null to clear it.

  • servicestring

    Up to 128 characters, e.g. UPS Ground. Send null to clear it.

  • serviceCodestring

    Up to 128 characters. Send null to clear it.

  • externalIdstring

    Your own id for the shipment, up to 128 characters. Send null to clear it.

  • externalOrderIdstring

    Your order id, up to 128 characters. GET /shipments can filter and search by it. Send null to clear it.

  • originCountrystring

    Up to 128 characters. Free text; ISO 3166-1 alpha-2 such as US is recommended. Send null to clear it.

  • destinationCountrystring

    Up to 128 characters, same format as originCountry. Send null to clear it.

  • originPostalCodestring

    Up to 64 characters. Send null to clear it.

  • destinationPostalCodestring

    Up to 64 characters. Send null to clear it.

  • metadataobject

    A JSON object, up to 16 KB serialized, merged into the existing metadata. Existing keys are overwritten, others kept; there is no way to remove a key, and null is ignored.

Response

200
The updated Shipment, without checkpoints.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

  • 400
    INVALID_CUSTOMER

    customerId does not belong to your organization.

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

The tracking number, carrier, archive state and tracking status cannot be changed here; unknown fields are ignored. An empty body {} succeeds and only refreshes update_at.

Sending customerEmail, customerPhone or customerName links the shipment to the matching customer (created if new).

Delete a shipment

Permanently delete a shipment and everything attached to it.

DELETE/shipments/:id
shipments:write
curl -X DELETE "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment deleted successfully",
  "data": {
    "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "trackingNumber": "1Z999AA10123456784",
    "deleted": true
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

200
The id and tracking number of what was deleted.

Errors

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

Deleting is permanent and cannot be undone. Its tracking events, exceptions and returns are deleted with it, and the shipment allowance it used is not refunded. To keep the history, archive instead.

Send no Content-Type header and no body on this request: a JSON content type with an empty body is rejected with 400 FST_ERR_CTP_EMPTY_JSON_BODY.

Delete shipments in bulk

Permanently delete several shipments in one request.

POST/shipments/bulk-delete
shipments:write
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments/bulk-delete" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "shipmentIds": [
    "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "c91d0a73-5be2-4a18-8d64-0f7e3b2c1a59"
  ]
}'
Response · 200 OK
{
  "statusCode": 200,
  "message": "Successfully deleted 2 shipments",
  "data": {
    "totalRequested": 2,
    "deletedCount": 2,
    "deletedIds": [
      "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "c91d0a73-5be2-4a18-8d64-0f7e3b2c1a59"
    ]
  }
}

Request body (JSON)

  • shipmentIdsstring[]required

    1 to 100 ids (each 1 to 64 characters) of the shipments to delete. Ids that do not exist in your organization are skipped without an error.

Response

200
How many ids you sent and which shipments were actually deleted.

Errors

  • 400
    VALIDATION_ERROR

    shipmentIds is missing, is not an array of strings, is empty, or holds more than 100 ids.

Plus the general errors every request can get (401, 403, 429, 5xx).

Permanent, with the same effects as Delete a shipment. Compare deletedCount with totalRequested to spot ids that were skipped; duplicates in your list count toward totalRequested.

Archive a shipment

Stop tracking a shipment and hide it from the default list, keeping its data.

POST/shipments/:id/archive
shipments:write
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/archive" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment archived successfully",
  "data": {
    "id": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "tracking_number": "1Z999AA10123456784",
    "courier_code": "ups",
    "order_number": "ORD-10045",
    "order_date": null,
    "created_at": "2026-10-20T14:32:08.417Z",
    "update_at": "2026-10-21T08:00:12.905Z",
    "delivery_status": "pending",
    "archived": "archived",
    "updating": false,
    "source": "API",
    "destination_country": "US",
    "destination_state": null,
    "destination_city": null,
    "origin_country": null,
    "origin_state": null,
    "origin_city": null,
    "tracking_postal_code": null,
    "tracking_ship_date": null,
    "tracking_destination_country": "US",
    "tracking_origin_country": null,
    "tracking_key": null,
    "tracking_courier_account": null,
    "customer_name": "Jane Doe",
    "customer_email": "[email protected]",
    "customer_sms": null,
    "recipient_postcode": "78701",
    "order_id": "ORD-10045",
    "title": null,
    "logistics_channel": "UPS Ground",
    "note": "Leave at front desk",
    "label": null,
    "signed_by": null,
    "service_code": "UPS Ground",
    "weight": null,
    "weight_kg": null,
    "product_type": null,
    "pieces": null,
    "dimension": null,
    "previously": null,
    "destination_track_number": null,
    "exchange_number": null,
    "scheduled_delivery_date": null,
    "scheduled_address": null,
    "substatus": null,
    "status_info": null,
    "latest_event": null,
    "latest_checkpoint_time": null,
    "transit_time": 1,
    "origin_info": {
      "courier_code": "ups",
      "courier_phone": "1.800.742.5877",
      "weblink": "https://www.ups.com/",
      "tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
      "reference_number": "ups",
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "destination_info": {
      "courier_code": null,
      "courier_phone": null,
      "weblink": null,
      "tracking_link": null,
      "reference_number": null,
      "milestone_date": {
        "inforeceived_date": null,
        "pickup_date": null,
        "outfordelivery_date": null,
        "delivery_date": null,
        "returning_date": null,
        "returned_date": null
      },
      "pickup_date": null,
      "departed_airport_date": null,
      "arrived_abroad_date": null,
      "customs_received_date": null,
      "trackinfo": []
    },
    "organizationId": "5d0e3b0a-7c1f-4e92-b6a8-3f4d2e1a9c70",
    "trackingNumber": "1Z999AA10123456784",
    "normalizedTrackingNumber": "1Z999AA10123456784",
    "carrier": {
      "id": "carr_ups",
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "status": "archived",
    "currentTrackingStatus": "pending",
    "currentTrackingStatusAt": "2026-10-20T14:32:08.417Z",
    "service": "UPS Ground",
    "externalId": null,
    "externalOrderId": "ORD-10045",
    "originPostalCode": null,
    "destinationPostalCode": "78701",
    "metadata": {
      "warehouse": "AUS-1",
      "note": "Leave at front desk",
      "customer_name": "Jane Doe",
      "customer_email": "[email protected]"
    },
    "createdAt": "2026-10-20T14:32:08.417Z",
    "updatedAt": "2026-10-21T08:00:12.905Z",
    "archivedAt": "2026-10-21T08:00:12.905Z"
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

200
The archived Shipment.

Errors

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

There is no un-archive. An archived shipment can still be retrieved by id and listed with status=archived, but it can no longer be retracked. Archiving again only refreshes archivedAt.

Send no Content-Type header and no body on this request (see Delete a shipment).

Refresh tracking

Ask for an immediate carrier refresh instead of waiting for the next scheduled one.

POST/shipments/:id/retrack
shipments:writeNeeds an active subscription
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/retrack" \
  -H "Authorization: Bearer $API_KEY"
Response · 202 Accepted
{
  "statusCode": 202,
  "message": "Retrack job enqueued successfully",
  "data": {
    "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "status": "retrack_enqueued",
    "message": "Tracking refresh job enqueued successfully"
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

202
The refresh was queued. It runs in the background: read the result with Retrieve a shipment.

Errors

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

  • 409
    SHIPMENT_NOT_TRACKABLE

    The shipment is archived, has reached a final status (delivered, cancelled, return_to_sender, returned) or is older than 60 days.

  • 429
    RETRACK_COOLDOWN

    A refresh of this shipment started less than a minute ago. The response carries no Retry-After header; wait 60 seconds.

  • 503
    QUEUE_UNAVAILABLE

    The refresh could not be queued. Retry after the Retry-After header (5 seconds).

Plus the general errors every request can get (401, 403, 429, 5xx).

Send no Content-Type header and no body on this request (see Delete a shipment).

Tracking

Tracking status, scan events and live carrier lookups.

Get tracking status

The current tracking status of one shipment and how its latest carrier refresh went. A lighter call than retrieving the whole shipment.

GET/shipments/:id/tracking
shipments:read
curl "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/tracking" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Tracking info retrieved successfully",
  "data": {
    "trackingNumber": "1Z999AA10123456784",
    "status": "active",
    "currentTrackingStatus": "in_transit",
    "currentTrackingStatusAt": "2026-10-20T09:15:00.000Z",
    "carrierId": "carr_ups",
    "service": "UPS Ground",
    "syncState": {
      "status": "completed",
      "lastAttemptAt": "2026-10-20T14:40:02.118Z",
      "lastCompletedAt": "2026-10-20T14:40:03.552Z"
    }
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

200
The status fields, plus syncState describing the latest refresh (pending, processing, completed or failed), or null if the shipment has never been refreshed.

Errors

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

status is the archive state (active or archived); currentTrackingStatus is where the parcel is. See Statuses.

List tracking events

The carrier’s scan events for one shipment, one page at a time.

GET/shipments/:id/tracking/events
shipments:read
curl "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/tracking/events?limit=20" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Tracking events retrieved successfully",
  "data": [
    {
      "id": "ev_3f9a1c07d2b84e51",
      "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "eventAt": "2026-10-20T09:15:00.000Z",
      "normalizedStatus": "in_transit",
      "providerStatus": "Departed from Facility",
      "description": "Departed from Facility",
      "providerType": "ups",
      "locationCity": "Louisville",
      "locationState": "KY",
      "locationCountry": "US",
      "locationPostalCode": null,
      "isEstimated": false
    }
  ],
  "pagination": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Query parameters

  • pageinteger

    Page number, starting at 1.

    Default 1
  • limitinteger

    Items per page, 1 to 100.

    Default 20
  • sortOrderstring

    Order by event time. desc puts the newest scan first.

    One ofascdescDefault desc

Response

200
An array of events and a pagination object.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

Plus the general errors every request can get (401, 403, 429, 5xx).

normalizedStatus is one of the tracking statuses; providerStatus is the carrier’s own wording. isEstimated marks a scan the carrier predicted rather than recorded.

Look up by tracking number

Find one of your shipments by its tracking number and get a compact status with its latest events. You do not need the shipment id.

GET/tracking/:trackingNumber
shipments:read
curl "https://track360.tdccommerce.com/api/v1/tracking/1Z999AA10123456784" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Tracking details retrieved successfully",
  "data": {
    "tracking_number": "1Z999AA10123456784",
    "status": "in_transit",
    "carrier": "United Parcel Service (UPS)",
    "origin": "US",
    "destination": "78701, US",
    "events": [
      {
        "id": "ev_3f9a1c07d2b84e51",
        "timestamp": "2026-10-20T09:15:00.000Z",
        "description": "Departed from Facility",
        "location": "Louisville, KY, US",
        "source": "ups"
      }
    ]
  }
}

Path parameters

  • trackingNumberstringrequired

    The tracking number, URL-encoded. Matched ignoring case, spaces and hyphens, across all carriers.

Response

200
A compact view, not a Shipment: the most recent shipment of yours with that number (archived ones included) and up to its 50 newest events. origin and destination are postal code, country, or the words Origin / Destination when unknown.

Errors

  • 404
    TRACKING_NUMBER_NOT_FOUND

    None of your shipments has that tracking number.

Plus the general errors every request can get (401, 403, 429, 5xx).

status is the tracking status, e.g. in_transit. location is omitted from an event when it is unknown.

Look up live at the carrier

Ask a carrier for the current tracking of any tracking number right now, without creating a shipment.

POST/carriers/tracking
shipments:readshipments:writeif you send shipmentIdNeeds an active subscription
curl -X POST "https://track360.tdccommerce.com/api/v1/carriers/tracking" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "trackingNumber": "1Z999AA10123456784",
  "carrierCode": "ups"
}'
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment tracking information retrieved successfully",
  "data": {
    "tracking": {
      "trackingNumber": "1Z999AA10123456784",
      "carrierCode": "ups",
      "status": "IN_TRANSIT",
      "events": [
        {
          "normalizedStatus": "IN_TRANSIT",
          "normalizedMessage": "Departed from Facility",
          "rawEvent": "Departed from Facility",
          "rawStatus": "DP",
          "rawPayload": {},
          "timestamp": "2026-10-20T09:15:00.000Z",
          "location": {
            "city": "Louisville",
            "state": "KY",
            "country": "US"
          }
        }
      ],
      "estimatedDeliveryAt": "2026-10-22T20:00:00.000Z"
    },
    "resolutionReason": "platform_account",
    "providerType": "platform_carrier"
  }
}

Request body (JSON)

  • trackingNumberstringrequired

    The tracking number to look up. At least one character must be something other than a space or hyphen.

  • carrierCodestringrequired

    The carrier to ask, e.g. ups.

  • shipmentIdstring

    Also record the resolved provider on this shipment. Requires the shipments:write scope. An id that is not yours is ignored without an error.

Response

200
tracking is the carrier’s answer, providerType how it was reached (customer_carrier, platform_carrier, trackingmore, custom_carrier, test) and resolutionReason why (customer_account, platform_account, custom_carrier, fallback).

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

  • 403
    no code

    You sent shipmentId with a key that lacks shipments:write. Unlike other 403s this one has no code.

  • 502
    SERVICE_UNAVAILABLE

    The carrier could not be reached, failed, or did not know the number. The message is generic and does not say which; retry later.

Plus the general errors every request can get (401, 403, 429, 5xx).

The status values here are UPPER_CASE (IN_TRANSIT, DELIVERED, ARRIVED_AT_FACILITY, …), unlike the lower-case statuses of every other endpoint. The result also includes each event’s rawPayload and the provider’s own reference.

Each lookup spends a call to a carrier API on your behalf, so use it sparingly. For ongoing tracking, create a shipment instead.

Returns

Check eligibility, request returns and move them through their lifecycle.

Check return eligibility

Whether a return can be started for a shipment right now, and if not, why.

GET/shipments/:id/returns/eligibility
returns:read
curl "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/returns/eligibility" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Return eligibility evaluated",
  "data": {
    "eligible": true,
    "reason": "eligible"
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Response

200
eligible and a reason: eligible, or one of provider_unavailable, shipment_archived, return_already_exists, tracking_provider_does_not_support_returns, carrier_account_disabled, carrier_does_not_support_returns.

Errors

No errors specific to this endpoint. Every request can also get the general errors (401, 403, 429, 5xx).

This endpoint never answers 404: a shipment that does not exist (or is not yours) gives eligible: false with reason: "provider_unavailable".

Returns can only be started for FedEx and UPS shipments tracked through an active carrier account. Shipments from other carriers, or tracked through the fallback provider, are not eligible.

Create a return

Record a return request for a shipment. The return starts in the requested status.

POST/shipments/:id/returns
returns:writeNeeds the Returns feature
curl -X POST "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/returns" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reasonCode": "item_damaged",
  "reasonDescription": "Box arrived crushed"
}'
Response · 201 Created
{
  "statusCode": 201,
  "message": "Return requested successfully",
  "data": {
    "id": "ret_8f2c41d7a09b3e65",
    "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "trackingNumber": "1Z999AA10123456784",
    "externalOrderId": "ORD-10045",
    "carrier": {
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "customerName": "Jane Doe",
    "customerEmail": "[email protected]",
    "status": "requested",
    "reasonCode": "item_damaged",
    "reasonDescription": "Box arrived crushed",
    "requestedAt": "2026-10-20T15:01:11.002Z",
    "approvedAt": null,
    "rejectedAt": null,
    "cancelledAt": null,
    "completedAt": null,
    "returnTrackingNumber": null,
    "returnLabelReference": null,
    "allowedTransitions": [
      "pending_approval",
      "approved",
      "rejected",
      "cancelled"
    ],
    "createdAt": "2026-10-20T15:01:11.002Z",
    "updatedAt": "2026-10-20T15:01:11.002Z"
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Request body (JSON)

  • reasonCodestringrequired

    Why the item is coming back.

    One ofcustomer_changed_mindwrong_itemitem_damageditem_defectivenot_as_describedarrived_too_lateduplicate_orderother
  • reasonDescriptionstring

    Up to 2,000 characters, trimmed.

Response

201
The new return.

Errors

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

  • 402
    FEATURE_NOT_IN_PLAN

    Your plan does not include Returns. The body also carries "feature": "returns".

  • 400
    VALIDATION_ERROR

    reasonCode is missing or not one of the listed values, or the body has a field not listed here (unknown fields are rejected).

  • 404
    SHIPMENT_NOT_FOUND

    No shipment with that id exists in your organization.

  • 409
    RETURN_ALREADY_EXISTS

    The shipment already has a return in progress. Only one can be active at a time.

  • 422
    RETURN_NOT_ELIGIBLE

    The shipment cannot be returned; the message says why. Check eligibility first.

Plus the general errors every request can get (401, 403, 429, 5xx).

Creating a return records the request and its status. It does not create a carrier label: returnTrackingNumber and returnLabelReference stay null.

The plan check runs before body validation, so a plan without Returns gets 402 even for an invalid body.

List a shipment’s returns

The returns recorded for one shipment, newest first.

GET/shipments/:id/returns
returns:read
curl "https://track360.tdccommerce.com/api/v1/shipments/b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab/returns?limit=20" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Returns retrieved successfully",
  "data": [
    {
      "id": "ret_8f2c41d7a09b3e65",
      "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "trackingNumber": "1Z999AA10123456784",
      "externalOrderId": "ORD-10045",
      "carrier": {
        "code": "ups",
        "name": "United Parcel Service (UPS)"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "customerName": "Jane Doe",
      "customerEmail": "[email protected]",
      "status": "requested",
      "reasonCode": "item_damaged",
      "reasonDescription": "Box arrived crushed",
      "requestedAt": "2026-10-20T15:01:11.002Z",
      "approvedAt": null,
      "rejectedAt": null,
      "cancelledAt": null,
      "completedAt": null,
      "returnTrackingNumber": null,
      "returnLabelReference": null,
      "allowedTransitions": [
        "pending_approval",
        "approved",
        "rejected",
        "cancelled"
      ],
      "createdAt": "2026-10-20T15:01:11.002Z",
      "updatedAt": "2026-10-20T15:01:11.002Z"
    }
  ],
  "pagination": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Path parameters

  • idstringrequired

    The shipment id (the id field of a Shipment).

Query parameters

  • pageinteger

    Page number, starting at 1.

    Default 1
  • limitinteger

    Items per page, 1 to 100.

    Default 20
  • statusstring

    Only returns in this status.

    One ofrequestedpending_approvalapprovedrejectedlabel_generatedin_transitreceivedcancelled

Response

200
An array of returns and a pagination object.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

Plus the general errors every request can get (401, 403, 429, 5xx).

An unknown shipment id is not an error: the list is simply empty.

List returns

Every return in your organization, newest first.

GET/returns
returns:read
curl "https://track360.tdccommerce.com/api/v1/returns?limit=20&status=requested" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Returns retrieved successfully",
  "data": [
    {
      "id": "ret_8f2c41d7a09b3e65",
      "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "trackingNumber": "1Z999AA10123456784",
      "externalOrderId": "ORD-10045",
      "carrier": {
        "code": "ups",
        "name": "United Parcel Service (UPS)"
      },
      "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
      "customerName": "Jane Doe",
      "customerEmail": "[email protected]",
      "status": "requested",
      "reasonCode": "item_damaged",
      "reasonDescription": "Box arrived crushed",
      "requestedAt": "2026-10-20T15:01:11.002Z",
      "approvedAt": null,
      "rejectedAt": null,
      "cancelledAt": null,
      "completedAt": null,
      "returnTrackingNumber": null,
      "returnLabelReference": null,
      "allowedTransitions": [
        "pending_approval",
        "approved",
        "rejected",
        "cancelled"
      ],
      "createdAt": "2026-10-20T15:01:11.002Z",
      "updatedAt": "2026-10-20T15:01:11.002Z"
    }
  ],
  "pagination": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Query parameters

  • pageinteger

    Page number, starting at 1.

    Default 1
  • limitinteger

    Items per page, 1 to 100.

    Default 20
  • statusstring

    Only returns in this status.

    One ofrequestedpending_approvalapprovedrejectedlabel_generatedin_transitreceivedcancelled

Response

200
An array of returns and a pagination object.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

Plus the general errors every request can get (401, 403, 429, 5xx).

A return’s allowedTransitions lists the statuses it can move to next. requested → pending_approval, approved, rejected, cancelled; pending_approval → approved, rejected, cancelled; approved → label_generated, cancelled; label_generated → in_transit, cancelled; in_transit → received. received, rejected and cancelled are final.

Summarize returns

How many returns you have in total and in each status.

GET/returns/summary
returns:read
curl "https://track360.tdccommerce.com/api/v1/returns/summary" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Return summary retrieved successfully",
  "data": {
    "total": 5,
    "byStatus": {
      "requested": 2,
      "pending_approval": 0,
      "approved": 1,
      "rejected": 0,
      "label_generated": 0,
      "in_transit": 1,
      "received": 1,
      "cancelled": 0
    }
  }
}

Response

200
Counts, with every status present (zero when empty).

Errors

No errors specific to this endpoint. Every request can also get the general errors (401, 403, 429, 5xx).

Update a return’s status

Move a return to its next status.

PATCH/returns/:id/status
returns:write
curl -X PATCH "https://track360.tdccommerce.com/api/v1/returns/ret_8f2c41d7a09b3e65/status" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "approved"
}'
Response · 200 OK
{
  "statusCode": 200,
  "message": "Return status updated successfully",
  "data": {
    "id": "ret_8f2c41d7a09b3e65",
    "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
    "trackingNumber": "1Z999AA10123456784",
    "externalOrderId": "ORD-10045",
    "carrier": {
      "code": "ups",
      "name": "United Parcel Service (UPS)"
    },
    "customerId": "0c4f6a52-9d1e-4b7a-8e33-5a2f1c6d9b04",
    "customerName": "Jane Doe",
    "customerEmail": "[email protected]",
    "status": "approved",
    "reasonCode": "item_damaged",
    "reasonDescription": "Box arrived crushed",
    "requestedAt": "2026-10-20T15:01:11.002Z",
    "approvedAt": "2026-10-20T15:20:00.310Z",
    "rejectedAt": null,
    "cancelledAt": null,
    "completedAt": null,
    "returnTrackingNumber": null,
    "returnLabelReference": null,
    "allowedTransitions": [
      "label_generated",
      "cancelled"
    ],
    "createdAt": "2026-10-20T15:01:11.002Z",
    "updatedAt": "2026-10-20T15:20:00.310Z"
  }
}

Path parameters

  • idstringrequired

    The return id (ret_…).

Request body (JSON)

  • statusstringrequired

    The status to move to. It must be one of the return’s allowedTransitions.

    One ofrequestedpending_approvalapprovedrejectedlabel_generatedin_transitreceivedcancelled

Response

200
The updated return. Entering approved, rejected, cancelled or received stamps approvedAt, rejectedAt, cancelledAt or completedAt.

Errors

  • 400
    VALIDATION_ERROR

    status is missing or unknown, or the body has another field (unknown fields are rejected).

  • 404
    RETURN_NOT_FOUND

    No return with that id exists in your organization.

  • 422
    INVALID_RETURN_TRANSITION

    The return cannot move to that status from its current one, for example A return that is approved cannot be marked received.

Plus the general errors every request can get (401, 403, 429, 5xx).

A return’s allowedTransitions lists the statuses it can move to next. requested → pending_approval, approved, rejected, cancelled; pending_approval → approved, rejected, cancelled; approved → label_generated, cancelled; label_generated → in_transit, cancelled; in_transit → received. received, rejected and cancelled are final.

This changes the status in your account only; it does not contact the carrier or generate a label.

Exceptions

Read the delivery problems detected on your shipments.

List exceptions

Delivery problems detected on your shipments (failed delivery attempts, delays, carrier-reported exceptions), most recently detected first.

GET/exceptions
exceptions:read
curl "https://track360.tdccommerce.com/api/v1/exceptions?status=open&limit=20" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Exceptions retrieved successfully",
  "data": [
    {
      "id": "exc_8e0c2a41f7b94d3aa51e6c0d92b7f314",
      "shipmentId": "b7c1f2e4-3a58-4d0e-9f61-2c8d5a7e90ab",
      "trackingNumber": "1Z999AA10123456784",
      "externalOrderId": "ORD-10045",
      "carrier": {
        "code": "ups",
        "name": "United Parcel Service (UPS)"
      },
      "exceptionType": "delivery_attempt_failed",
      "code": "exception",
      "status": "open",
      "severity": "high",
      "title": "Delivery attempt failed",
      "description": "Delivery attempted; recipient not available",
      "firstDetectedAt": "2026-10-20T13:02:00.000Z",
      "lastDetectedAt": "2026-10-20T13:02:00.000Z",
      "resolvedAt": null,
      "resolutionCode": null,
      "resolutionNotes": null,
      "allowedTransitions": [
        "acknowledged",
        "in_progress",
        "dismissed"
      ],
      "createdAt": "2026-10-20T13:02:04.210Z",
      "updatedAt": "2026-10-20T13:02:04.210Z"
    }
  ],
  "pagination": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Query parameters

  • pageinteger

    Page number, starting at 1.

    Default 1
  • limitinteger

    Items per page, 1 to 100.

    Default 20
  • statusstring

    Only exceptions in this status.

    One ofopenacknowledgedin_progressresolveddismissed
  • severitystring

    Only exceptions of this severity.

    One oflowmediumhighcritical

Response

200
An array of exceptions and a pagination object.

Errors

  • 400
    VALIDATION_ERROR

    A parameter or body field is missing, has the wrong type or is out of range. details[].path names the field.

Plus the general errors every request can get (401, 403, 429, 5xx).

Exceptions are raised by tracking and are read-only with an API key; they are worked through in the dashboard. An exception resolves itself (resolutionCode auto_delivered) when its shipment is delivered.

exceptionType is one of delivery_delay, address_issue, carrier_delay, weather_delay, damaged, lost, delivery_attempt_failed, recipient_unavailable, customs_hold, customs_issue, return_to_sender, unknown. allowedTransitions lists the statuses it can move to in the dashboard.

Summarize exceptions

How many exceptions you have in total, in each status, and how many unresolved ones there are of each severity.

GET/exceptions/summary
exceptions:read
curl "https://track360.tdccommerce.com/api/v1/exceptions/summary" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Exception summary retrieved successfully",
  "data": {
    "total": 7,
    "byStatus": {
      "open": 3,
      "acknowledged": 1,
      "in_progress": 1,
      "resolved": 2,
      "dismissed": 0
    },
    "unresolvedBySeverity": {
      "low": 0,
      "medium": 1,
      "high": 3,
      "critical": 1
    }
  }
}

Response

200
unresolvedBySeverity counts every exception that is not resolved or dismissed.

Errors

No errors specific to this endpoint. Every request can also get the general errors (401, 403, 429, 5xx).

Reports

Analytics for your shipments, carriers and notifications, and CSV exports.

Dashboard totals

Headline numbers for a period: shipments, deliveries, exceptions and returns.

GET/reports/dashboard
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/dashboard" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Dashboard retrieved successfully",
  "data": {
    "summary": {
      "totalShipments": 412,
      "deliveredShipments": 331,
      "exceptions": 18,
      "returns": 6
    },
    "filters": {
      "dateRange": {
        "start": "2026-09-20T14:32:08.417Z",
        "end": "2026-10-20T14:32:08.417Z"
      },
      "timezone": "UTC"
    },
    "generatedAt": "2026-10-20T14:32:08.512Z",
    "dataFreshness": {
      "asOf": "2026-10-20T14:32:08.512Z",
      "mode": "near_real_time"
    }
  }
}

Query parameters

  • startstring

    Start of the window (inclusive), any date or ISO 8601 timestamp. Defaults to 30 days ago and is never earlier than your plan’s analytics retention.

  • endstring

    End of the window (exclusive). Defaults to now.

Response

200
exceptions and returns count those created in the window.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

Reports are computed in UTC over shipments created in the window. filters.dateRange echoes the window actually used, after start is clamped to your plan’s analytics retention.

Shipments created per day

How many shipments were created on each day of a period.

GET/reports/shipments
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/shipments" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment report retrieved successfully",
  "data": {
    "summary": {},
    "series": [
      {
        "date": "2026-10-19 00:00:00",
        "createdCount": 188
      },
      {
        "date": "2026-10-20 00:00:00",
        "createdCount": 224
      }
    ],
    "filters": {
      "dateRange": {
        "start": "2026-09-20T14:32:08.417Z",
        "end": "2026-10-20T14:32:08.417Z"
      },
      "timezone": "UTC"
    },
    "generatedAt": "2026-10-20T14:32:08.512Z",
    "dataFreshness": {
      "asOf": "2026-10-20T14:32:08.512Z",
      "mode": "near_real_time"
    }
  }
}

Query parameters

  • startstring

    Start of the window (inclusive), any date or ISO 8601 timestamp. Defaults to 30 days ago and is never earlier than your plan’s analytics retention.

  • endstring

    End of the window (exclusive). Defaults to now.

Response

200
series has one point per UTC day that has shipments; days with none are left out. date is YYYY-MM-DD HH:mm:ss.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

Reports are computed in UTC over shipments created in the window. filters.dateRange echoes the window actually used, after start is clamped to your plan’s analytics retention.

Delivery performance

How many shipments from a period are delivered and how long they took.

GET/reports/delivery
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/delivery" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Delivery report retrieved successfully",
  "data": {
    "summary": {
      "totalDelivered": 331,
      "avgTransitTime": 249120
    },
    "filters": {
      "dateRange": {
        "start": "2026-09-20T14:32:08.417Z",
        "end": "2026-10-20T14:32:08.417Z"
      },
      "timezone": "UTC"
    },
    "generatedAt": "2026-10-20T14:32:08.512Z",
    "dataFreshness": {
      "asOf": "2026-10-20T14:32:08.512Z",
      "mode": "near_real_time"
    }
  }
}

Query parameters

  • startstring

    Start of the window (inclusive), any date or ISO 8601 timestamp. Defaults to 30 days ago and is never earlier than your plan’s analytics retention.

  • endstring

    End of the window (exclusive). Defaults to now.

Response

200
avgTransitTime is in seconds (from creation to the last status change) and null when nothing was delivered.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

Reports are computed in UTC over shipments created in the window. filters.dateRange echoes the window actually used, after start is clamped to your plan’s analytics retention.

Carrier performance

Volume and delivery rate for each carrier over a period.

GET/reports/carriers
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/carriers" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Carrier report retrieved successfully",
  "data": {
    "items": [
      {
        "carrier": "United Parcel Service (UPS)",
        "volume": 240,
        "delivery_rate": 82.5
      },
      {
        "carrier": "FedEx",
        "volume": 172,
        "delivery_rate": 78.4
      }
    ],
    "summary": {},
    "series": [
      {
        "carrierId": "carr_ups",
        "carrierName": "United Parcel Service (UPS)",
        "totalShipments": 240,
        "deliveredShipments": 198,
        "deliveryRate": 82.5,
        "avgTransitTime": 241200
      },
      {
        "carrierId": "carr_fedex",
        "carrierName": "FedEx",
        "totalShipments": 172,
        "deliveredShipments": 135,
        "deliveryRate": 78.4,
        "avgTransitTime": 259800
      }
    ],
    "filters": {
      "dateRange": {
        "start": "2026-09-20T14:32:08.417Z",
        "end": "2026-10-20T14:32:08.417Z"
      },
      "timezone": "UTC"
    },
    "generatedAt": "2026-10-20T14:32:08.512Z"
  }
}

Query parameters

  • startstring

    Start of the window (inclusive), any date or ISO 8601 timestamp. Defaults to 30 days ago and is never earlier than your plan’s analytics retention.

  • endstring

    End of the window (exclusive). Defaults to now.

Response

200
items is the compact view; series adds ids and transit time (seconds). Rates are percentages from 0 to 100, not rounded. Shipments without a carrier are grouped as Unknown.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

Reports are computed in UTC over shipments created in the window. filters.dateRange echoes the window actually used, after start is clamped to your plan’s analytics retention.

Shipment flow

How many of your current shipments are in each tracking status.

GET/reports/flow
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/flow" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Shipment flow pipeline retrieved successfully",
  "data": {
    "stages": [
      {
        "status": "pending",
        "count": 12
      },
      {
        "status": "unknown",
        "count": 0
      },
      {
        "status": "label_created",
        "count": 9
      },
      {
        "status": "pre_transit",
        "count": 4
      },
      {
        "status": "picked_up",
        "count": 21
      },
      {
        "status": "in_transit",
        "count": 64
      },
      {
        "status": "out_for_delivery",
        "count": 17
      },
      {
        "status": "delivered",
        "count": 331
      },
      {
        "status": "exception",
        "count": 5
      },
      {
        "status": "failed",
        "count": 1
      },
      {
        "status": "available_for_pickup",
        "count": 2
      },
      {
        "status": "return_to_sender",
        "count": 0
      },
      {
        "status": "returned",
        "count": 3
      },
      {
        "status": "cancelled",
        "count": 0
      }
    ]
  }
}

Response

200
One stage per tracking status, zeros included: pending, unknown, label_created, pre_transit, picked_up, in_transit, out_for_delivery, delivered, exception, failed, available_for_pickup, return_to_sender, returned, cancelled. It counts every shipment that is not archived, regardless of when it was created.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

This report is not date-ranged: a valid start and end are accepted and ignored. A malformed range is still refused like on every other report.

Delivery trend

The share of each recent day’s new shipments that are now delivered.

GET/reports/delivery-trend
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/delivery-trend" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Delivery trend retrieved successfully",
  "data": {
    "points": [
      {
        "date": "2026-10-18",
        "delivery_rate": 71
      },
      {
        "date": "2026-10-19",
        "delivery_rate": 64
      },
      {
        "date": "2026-10-20",
        "delivery_rate": 12
      }
    ]
  }
}

Response

200
One point per UTC day for the last 30 days, zero-filled. delivery_rate is a whole-number percentage from 0 to 100.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

This report is not date-ranged: a valid start and end are accepted and ignored. A malformed range is still refused like on every other report.

Notification delivery

How many customer notifications were delivered and how many failed.

GET/reports/notifications
analytics:read
curl "https://track360.tdccommerce.com/api/v1/reports/notifications" \
  -H "Authorization: Bearer $API_KEY"
Response · 200 OK
{
  "statusCode": 200,
  "message": "Notification metrics retrieved successfully",
  "data": {
    "sent": 1840,
    "failed": 23,
    "opened_rate": 99
  }
}

Response

200
All-time counts. opened_rate is the whole-number percentage of notifications that were delivered, delivered ÷ (delivered + failed); it does not measure opens.

Errors

  • 400
    VALIDATION_ERROR

    start or end cannot be parsed, or start is after end (end: start must not be after end).

Plus the general errors every request can get (401, 403, 429, 5xx).

This report is not date-ranged: a valid start and end are accepted and ignored. A malformed range is still refused like on every other report.

Export a report as CSV

Download shipments or carrier performance as a spreadsheet-ready CSV file.

POST/reports/exports
analytics:readNeeds the Report exports feature
curl -X POST "https://track360.tdccommerce.com/api/v1/reports/exports" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "shipments",
  "start": "2026-10-01",
  "end": "2026-10-21"
}' \
  -o report.csv
Response · 200 OK
Tracking number,Carrier,Tracking status,Status updated at,Archived state,Order ID,Service,Origin country,Destination country,Created at
1Z999AA10123456784,United Parcel Service (UPS),in_transit,2026-10-20T09:15:00.000Z,active,ORD-10045,UPS Ground,US,US,2026-10-20T14:32:08.417Z
794644790138,FedEx,pending,2026-10-20T13:10:44.001Z,active,ORD-10046,FedEx Ground,,US,2026-10-20T13:10:44.002Z

Request body (JSON)

  • typestringrequired

    What to export.

    One ofshipmentscarriers
  • startstring

    Start of the window (inclusive), any date or ISO 8601 timestamp. Defaults to 30 days ago and is never earlier than your plan’s analytics retention.

  • endstring

    End of the window (exclusive). Defaults to now.

Response

200
A CSV file, not the JSON envelope. UTF-8 with a byte-order mark and CRLF line endings. Cells that start with =, +, -, @ or a tab are prefixed with ' so spreadsheets do not run them as formulas. shipments columns: tracking number, carrier, tracking status, status updated at, archived state, order id, service, origin country, destination country, created at (newest first). carriers columns: carrier, shipments, delivered, delivery rate (%), average transit (hours).
  • Content-Type text/csv; charset=utf-8
  • Content-Disposition attachment; filename="<type>-YYYY-MM-DD.csv"
  • X-Row-Count Rows in the file.
  • X-Truncated true when more than 10,000 rows matched and the file was cut to the newest 10,000, otherwise false.

Errors

  • 402
    ACTIVE_SUBSCRIPTION_REQUIRED

    The organization has no active subscription.

  • 402
    FEATURE_NOT_IN_PLAN

    Your plan does not include Report exports. The body also carries "feature": "reportExports".

  • 400
    VALIDATION_ERROR

    type is missing or unknown, or the date range is invalid.

Plus the general errors every request can get (401, 403, 429, 5xx).

The file is cut at 10,000 rows without an error. Check the X-Truncated header, and narrow start / end when it is true.

Reports are computed in UTC over shipments created in the window. filters.dateRange echoes the window actually used, after start is clamped to your plan’s analytics retention.

© 2026 Track 360
PricingDocsAPI DocsBlogContactSign up