FreightTrackingAPI

API Reference

The FreightTrackingAPI REST API. All responses are JSON. GET /track/{bookingNumber} requires an API key; GET / and GET /health do not.

Authentication

Tracking requests require an API key in the x-api-key header. Create and manage keys in your dashboard. Publishable keys may only call GET /track/… and are restricted to domains you configure.

curl https://api.freighttrackingapi.com.au/track/2751234567 \
  -H "x-api-key: YOUR_API_KEY"

Base URL

https://api.freighttrackingapi.com.au

Endpoints

MethodPathAuthDescription
GET/track/{bookingNumber}x-api-keyTrack by carrier booking or reference number
GET/NoneAPI metadata: name, env, version (JSON)
GET/healthNoneLiveness: JSON { healthy: true } when the service is ready

Example GET /: { "name": "Freight Tracker API", "env": "production", "version": "…" }

GET /track/{bookingNumber}

Resolves the carrier from the booking number/BOL number format and returns voyage steps. Responses are cached for 24 hours. When a step has modeOfTransport is "VESSEL" and a non-empty vesselName, the response always includes vesselPosition: an object if a position was resolved from AIS-style data (automated lookup by vessel name), or null if lookup failed or no match. Other legs do not include vesselPosition.

Path parameters

ParameterTypeDescription
bookingNumberstringThe booking number/BOL number or reference number issued by the carrier (OOCL example: 2751234567)

Supported carriers

COSCO, Evergreen, Hapag-Lloyd, Maersk, OOCL, ZIM, ANL. The carrier is inferred from the booking number/BOL number format — you do not pass a carrier code. The JSON carrier field uses uppercase underscore codes, e.g. HAPAG_LLOYD, EVERGREEN.

Example request

curl https://api.freighttrackingapi.com.au/track/2751234567 \
  -H "x-api-key: YOUR_API_KEY"

Example response

{
  "bookingNumber": "2751234567",
  "mode": "ocean",
  "carrier": "OOCL",
  "cached": false,
  "fetchedAt": "2024-11-01T08:00:00.000Z",
  "expiresAt": "2024-11-02T08:00:00.000Z",
  "container": "TLLU310390-3",
  "steps": [
    {
      "stepIndex": 0,
      "modeOfTransport": "VESSEL",
      "vesselName": "OOCL EXAMPLE VESSEL",
      "voyageNumber": "042E",
      "portOfLoadingCode": "CNSHA",
      "portOfLoadingName": "Shanghai",
      "portOfDischargeCode": "USNYC",
      "portOfDischargeName": "New York",
      "etd": "2024-10-20T14:00:00.000Z",
      "eta": "2024-11-10T08:00:00.000Z",
      "container": "TLLU310390-3",
      "vesselPosition": {
        "mmsi": 211331640,
        "imo": 9811000,
        "lat": 1.29,
        "lng": 104.05,
        "speed": "14.2",
        "status": "Underway",
        "lastUpdated": "2024-11-01T07:45:00.000Z"
      }
    }
  ]
}

Response fields

FieldTypeDescription
bookingNumberstringThe booking number/BOL number as provided
mode"ocean" | "air"Transport mode (currently always ocean)
carrierstringResolved carrier code: COSCO, EVERGREEN, HAPAG_LLOYD, MAERSK, OOCL, ZIM, or ANL (uppercase, as returned in JSON)
cachedbooleantrue if this response was served from cache
fetchedAtISO 8601When this payload was last obtained from the carrier; unchanged on cache hits (still the original fetch time)
expiresAtISO 8601When the cache entry expires (24h TTL)
containerstring | nullRoot-level container number if resolved, or null
stepsarrayOrdered voyage legs — see Step object below

Step object

FieldTypeDescription
stepIndexnumberZero-based leg index
modeOfTransport"VESSEL" | "TRUCK" | "RAIL" | "UNKNOWN"Transport mode for this leg
vesselNamestring | nullVessel name when the carrier provides it; may be null or omitted per leg
voyageNumberstring | nullVoyage or service code when provided; may be null or omitted
portOfLoadingCodestring | nullPort of loading code when provided (often UN/LOCODE); may be null or omitted
portOfLoadingNamestring | nullHuman-readable port of loading; may be null or omitted
portOfDischargeCodestring | nullPort of discharge code when provided (often UN/LOCODE); may be null or omitted
portOfDischargeNamestring | nullHuman-readable port of discharge; may be null or omitted
etdISO 8601 | nullEstimated departure; null or omitted if unknown
etaISO 8601 | nullEstimated arrival; null or omitted if unknown
containerstring | nullContainer number for this voyage leg/step if resolved, or null
vesselPositionobject | nullOnly on steps with modeOfTransport VESSEL and a non-empty vesselName. Always present for those steps: object if resolved, otherwise null. See Vessel position object below.

Vessel position object

Populated when our systems can match the step's vesselName to a current position (trimmed, case-insensitive). Lat/lng are decimal degrees. All timestamps in JSON are ISO 8601 strings.

FieldTypeDescription
mmsinumberMaritime Mobile Service Identity
imonumber | nullIMO number from the matched vessel, or null when not provided
latnumberLatitude in decimal degrees
lngnumberLongitude in decimal degrees
speedstringSpeed over ground as a decimal string with one fractional digit (e.g. "14.2")
statusstringNavigation status label (e.g. Underway, At Anchor); may be an empty string if unknown
lastUpdatedISO 8601Time associated with the position snapshot

Error codes

StatusDescription
400Bad request — missing or empty booking number/BOL number after trimming, unknown or ambiguous carrier format, or carrier not available on this API
401Unauthorized — missing or invalid API key
403Forbidden — e.g. no active subscription on the key's account, monthly distinct-booking limit reached, or publishable key used outside an allowed domain/origin
429Too many requests — per-key rate limit; response may include a Retry-After header (seconds) and JSON body with message and retryAfterSec
500Internal server error — carrier or system failure

Error response shape

Most errors use Nest's JSON shape: statusCode and message (string or string array).

{
  "statusCode": 401,
  "message": "Invalid API key"
}

Example rate limit body:

{
  "statusCode": 429,
  "message": "Rate limit exceeded",
  "retryAfterSec": 42
}

Billing & rate limits

Subscribed plans include a monthly limit on distinct booking numbers/BOL numbers successfully tracked (HTTP 2xx) for your account in that billing period. The first successful track for a given booking in the period counts toward the limit; further successful requests for the same booking in the same period do not consume another slot. Failed requests (non-2xx) do not add usage toward that distinct-booking count.

Rate limits (requests per minute) apply per API key. On 429, honor Retry-After and backoff. Contact us at hello@recargo.com.au if you need a higher limit.