Skip to content

Conversion API

Send any tracking number, get one dcx number that resolves in public. Recognized carriers are converted for you; sources dcx can't reach on its own are fed by your own events. One public read endpoint, two authenticated write endpoints, JSON throughout.

Convert a number

Post a shipment with its source number. If dcx recognizes the carrier, it returns mode: managed and starts pulling events itself. If it doesn't, it returns mode: push — you become the source and send events to the endpoint below.

POST /api/dcx/v1/shipments
Authorization: Bearer dcx_live_...

{
  "client_reference": "order-88214",
  "source_tracking": "1Z999AA10123456784",
  "dest_city": "Portland",
  "dest_state": "OR"
}

201 {
  "tracking_id": "DCX4417829033556",
  "mode": "managed",
  "public_url": "https://www.dcxtracking.com/track/DCX4417829033556"
}

Idempotent on client_reference. Posting the same reference twice returns the original number rather than minting a second one, so retries are safe. Omit source_tracking and the shipment opens in push mode.

Send events (push mode)

For sources dcx can't read on its own, post the real events as you see them. Authenticated with the same bearer key, scoped to your own shipments.

POST /api/dcx/v1/events
Authorization: Bearer dcx_live_...

{
  "tracking_id": "DCX4417829033556",
  "events": [
    {
      "occurred_at": "2026-09-03T14:22:00Z",
      "status": "IN_TRANSIT",
      "description": "In transit",
      "location_city": null
    }
  ]
}

200 { "tracking_id": "DCX...", "status": "IN_TRANSIT", "events_received": 1 }

Events are deduplicated on a hash of timestamp, status, and description, so replaying a full history is safe. Timestamps dated in the future are rejected: dcx records events that happened, not events expected to happen.

Read a shipment

Public, no authentication. This is the endpoint aggregators and storefronts render from.

GET /api/dcx/v1/track/{tracking_id}
{
  "tracking_id": "DCX4417829033556",
  "status": "IN_TRANSIT",
  "estimated_delivery": "2026-09-08T21:00:00.000Z",
  "destination": "Portland, OR",
  "events": [
    {
      "timestamp": "2026-09-03T14:22:00.000Z",
      "status": "IN_TRANSIT",
      "description": "In transit",
      "location": null
    },
    {
      "timestamp": "2026-09-02T09:04:00.000Z",
      "status": "PRE_TRANSIT",
      "description": "Shipping label created",
      "location": "Snyder, TX 79549"
    }
  ]
}

Status values

PRE_TRANSIT
Accepted, not yet moving through a network
IN_TRANSIT
Moving through the delivery network
OUT_FOR_DELIVERY
On a vehicle for final delivery
DELIVERED
Delivery reported by the source network
EXCEPTION
Attempted, refused, held, or returning
UNKNOWN
No usable events available

Errors

A malformed number returns 400 with code invalid_number. A well-formed number with no matching shipment returns 404 with not_found. Upstream trouble returns 503 with internal_error. Reads are cached for 60 seconds.

Number format

DCX followed by 13 digits: 12 digits of payload and one Luhn check digit. The pattern is ^DCX\d{13}$. Payloads are random rather than sequential, so the format can't be walked to enumerate shipments.