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.