TrackJet API v1
A read-only REST API over TrackJet's detection engine and carrier directory — the same logic that powers the website and the MCP server. Multi-vertical: air cargo (MAWB), ocean containers (ISO 6346), Bill of Lading (SCAC), parcels, and postal (UPU S10). EU-hosted. No scraping of third-party aggregators.
https://trackjet.world/api/v1OpenAPI 3.1:
/api/v1/openapi.jsonRate limits: free: 60/min · pro: 600/min · enterprise: 6000/min (per API key). Responses carry
X-RateLimit-* headers; over-limit returns 429.Billing: disabled (all plans free).
Authentication
Send your API key as a Bearer token (the X-Api-Key header is also accepted):
Authorization: Bearer tjk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keys are issued by the TrackJet team. Treat a key like a password — it grants read access under your plan's rate limit. Every response includes an X-Request-Id you can quote in support requests.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v1/detect | Detect a number's format/vertical. Query: number. |
GET | /api/v1/track/{number} | Detect + resolve where to track (carrier URL + TrackJet URL). |
GET | /api/v1/carriers | List production carriers. Query: type, limit, offset. |
GET | /api/v1/carrier/{id} | A single carrier's metadata. |
GET | /api/v1/capabilities | Coverage snapshot (formats, counts, MCP info). |
GET | /api/v1/carbon | Rough freight CO2e estimate (GLEC/ISO 14083). Query: mode, weight_kg, distance_km. |
GET | /api/v1/track/{number}/qr | QR image (SVG/PNG) that opens the tracking page. No key required; embeddable in <img>. |
GET | /api/v1/track/{number}/stream | Server-Sent Events live stream (text/event-stream). Emits status events; closes with event: closed + a reason (no_live_feed when the carrier has no licensed event feed — DHL Group numbers stream real updates). |
GET·POST | /api/v1/webhooks | List / register webhooks (HMAC-signed deliveries). POST honours Idempotency-Key. |
POST | /api/graphql | GraphQL (alongside REST). Same key auth. Query: detect, carriers, carrier, capabilities. |
GET | /api/v1 | Service descriptor (no key required). |
Response envelope
{
"ok": true,
"data": { "...": "endpoint-specific" },
"meta": { "request_id": "…", "api_version": "v1" }
}
// errors:
{ "ok": false, "error": { "code": "unauthorized", "message": "…", "status": 401 }, "meta": { … } }
Examples
curl
curl -H "Authorization: Bearer $TRACKJET_API_KEY" \
"https://trackjet.world/api/v1/detect?number=020-12345675"
JavaScript (fetch)
const res = await fetch("https://trackjet.world/api/v1/detect?number=020-12345675", {
headers: { Authorization: `Bearer ${process.env.TRACKJET_API_KEY}` },
});
const { data } = await res.json();
console.log(data.primary, data.normalized);
PHP
$ch = curl_init("https://trackjet.world/api/v1/detect?number=020-12345675");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("TRACKJET_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
echo $data["data"]["normalized"];
Python
import os, requests
r = requests.get(
"https://trackjet.world/api/v1/detect",
params={"number": "020-12345675"},
headers={"Authorization": f"Bearer {os.environ['TRACKJET_API_KEY']}"},
)
print(r.json()["data"]["primary"])
GraphQL
curl -X POST "https://trackjet.world/api/graphql" \
-H "Authorization: Bearer $TRACKJET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ detect(number:\"020-12345675\"){ normalized matched matches{ type label } } }"}'
EPCIS 2.0 repository
Minimal conformant subset of GS1 EPCIS 2.0 (honest scope: ObjectEvent JSON only — no XML, no subscriptions, no full query language). Events are isolated per API key. EPCs whose digit-run matches a tracked shipment appear on its public page as "EPCIS (partner)", separate from the carrier chain.
curl -X POST "https://trackjet.world/api/v1/epcis/capture" \
-H "Authorization: Bearer $TRACKJET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"ObjectEvent","eventTime":"2026-06-11T09:00:00Z",
"eventTimeZoneOffset":"+00:00","action":"OBSERVE",
"bizStep":"urn:epcglobal:cbv:bizstep:shipping",
"epcList":["urn:epc:id:sscc:0037000.0123456789"],
"readPoint":{"id":"urn:epc:id:sgln:0037000.00729.0"}}'
curl -H "Authorization: Bearer $TRACKJET_API_KEY" \
"https://trackjet.world/api/v1/epcis/events?EPC=urn:epc:id:sscc:0037000.0123456789"
Webhooks
Register an HTTPS endpoint to receive shipment.status_changed events. Each delivery is signed:
curl -X POST "https://trackjet.world/api/v1/webhooks" \
-H "Authorization: Bearer $TRACKJET_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"url":"https://you.example/hook","events":"shipment.status_changed"}'
# response includes a one-time "secret".
Verify each delivery's X-TrackJet-Signature: sha256=<hmac>:
expected = "sha256=" + hmac_sha256(raw_request_body, your_secret)
if not hmac_compare(expected, header["X-TrackJet-Signature"]): reject()
Sandbox
Reserved TJTEST-* tracking numbers return deterministic, fully-synthetic lifecycles (timestamps in 2030, sandbox:true), so you can build and pin integration tests without a real parcel — happy path and edge cases:
| Number | Scenario |
|---|---|
TJTEST-DELIVERED | Full happy path ending delivered. |
TJTEST-IN-TRANSIT | Mid-journey, latest event in_transit. |
TJTEST-EXCEPTION | Carrier exception (damaged label), no delivery. |
TJTEST-CUSTOMS-HOLD | Held at customs awaiting import duties. |
TJTEST-RETURNED | Refused at the door, returned to sender. |
TJTEST-STALE | No scans for 14 days — exercise your staleness logic. |
TJTEST-NOT-FOUND | Always "no data" — exercise your empty state. |
curl -H "Authorization: Bearer $TRACKJET_API_KEY" \
"https://trackjet.world/api/v1/track/TJTEST-DELIVERED"
Webhook dry-run — fire one signed sandbox.test event at your registered endpoint through the real delivery pipeline (same X-TrackJet-Signature, same retry/log path):
curl -X POST "https://trackjet.world/api/v1/webhooks/<id>/test" \
-H "Authorization: Bearer $TRACKJET_API_KEY"
Transparency & verification
Every tracked chain's history is sealed into a SHA-256 hash chain (tjvt1), and all sealed heads are anchored in a public, append-only Merkle log (tjmt1). Three endpoints are public — no API key — because a transparency log is only credible when anyone can verify:
curl "https://trackjet.world/api/v1/shipments/<uuid>/proof" # tjvt1 chain proof
curl "https://trackjet.world/api/v1/shipments/<uuid>/inclusion" # tjmt1 Merkle inclusion proof
curl "https://trackjet.world/api/v1/transparency/roots" # append-only root history
Verify offline with the single-file, dependency-free tjverify CLI.
Notes
/api/v1/track/{number}returns detection + where to track. For live events use/api/v1/track/{number}/stream(SSE) — real updates exist only where TrackJet holds a carrier-licensed feed (DHL Group today); other numbers close immediately withno_live_feedinstead of fabricating events.- Statuses, when present, are normalised to:
pending · in_transit · out_for_delivery · delivered · exception · returned · unknown. - TrackJet is independent and EU-hosted; it does not scrape third-party tracking aggregators.