Broadpath API · v1

Build on live
cargo intelligence.

A REST API for everything in the Broadpath platform — container tracking, vessel positions, port intelligence. Bearer auth, JSON in, JSON out, generous rate limits, webhooks for the things you'd rather not poll.

~/track.sh
# Fetch a container's latest snapshot
curl https://broadpath.app/api/v1/containers/MEDU9091004 \
  -H "Authorization: Bearer bp_live_•••"

# Response (200 OK)
{
  "data": {
    "reference": "MEDU9091004",
    "shippingLine": "MSC",
    "status": "tracking",
    "journeyStatus": "in_transit",
    "pod": "Genoa",
    "etaAt": "2026-05-20T00:00:00.000Z",
    "updatedAt": "2026-05-14T03:00:00.000Z"
  }
}
12
Endpoints
600/min
Rate limit
<120ms
P95 latency
JSON
Format
Quickstart

Three steps. Five minutes.

No client library required — every endpoint is a plain HTTPS call returning JSON. Use whatever HTTP client your stack already has.

STEP 01

Create a key

API access is included on the Pro and Broker plans. Mint a key from Settings → API keys; the secret is shown once at creation, so copy it then.

→ broadpath.app/platform/settings.html
STEP 02

Make your first call

Authenticate with a Bearer header. Every response includes x-ratelimit-* headers so you can throttle proactively.

curl https://broadpath.app/api/v1/containers \
  -H "Authorization: Bearer bp_live_…"
STEP 03

Subscribe to webhooks

Skip polling. On the Broker plan, configure a signed HTTPS endpoint in Settings → Webhooks and we'll POST alert events the moment they fire — every delivery is HMAC-signed and logged.

Settings → Webhooks  ·  X-Broadpath-Signature: sha256=…
// API-based registration (POST /v1/webhooks) — coming soon

Authentication

Bearer tokens. Send your API key in the Authorization header on every request.

  • Key prefix bp_live_*
  • Header Authorization: Bearer …
  • Plan required Pro or Broker
  • Rotation Self-serve in Settings

The full secret is shown once at creation and stored only as an argon2 hash — keep it safe and revoke anytime in Settings.

Rate limits

Per-key limits over a fixed 60-second window. Every response carries the current budget so you can throttle proactively.

  • Pro plan 120 req/min
  • Broker plan 600 req/min
  • Headers X-RateLimit-Limit / -Remaining / -Reset
  • On 429 Retry-After (seconds)

Over the limit returns 429 with {"error":{"code":"RATE_LIMITED",…}}; wait Retry-After seconds.

Reference

Endpoints.

All endpoints are at https://broadpath.app/api/v1 and return JSON. Errors are { "error": { "code", "message" } } with the matching HTTP status. Machine-readable spec: openapi.json.

GET /v1/containers/:reference Container snapshot

Returns the latest known state of one container you track — reference, carrier, status, lane (POL/POD), ETA, last-free-day, and active customs holds. Scoped to your organization.

Returns

A data object with reference, referenceType, shippingLine, carrierScac, status, journeyStatus, pol, pod, etaAt, lastFreeDay, holdsActive, updatedAt.

curl
curl https://broadpath.app/api/v1/containers/MEDU9091004 \
  -H "Authorization: Bearer bp_live_•••"

{
  "data": {
    "reference": "MEDU9091004",
    "referenceType": "container",
    "shippingLine": "MSC",
    "carrierScac": "MSCU",
    "status": "tracking",
    "journeyStatus": "in_transit",
    "pol": "Guayaquil",
    "pod": "Genoa",
    "etaAt": "2026-05-20T00:00:00.000Z",
    "lastFreeDay": null,
    "holdsActive": 0,
    "updatedAt": "2026-05-14T03:00:00.000Z"
  }
}
GET /v1/containers/:reference/events Event timeline

Milestone timeline for a container you track — gate-in, load, departure, transhipment, arrival, discharge, customs, gate-out — in chronological order, capped to the most recent limit.

Query parameters

sinceISO date-time
Only return events occurring at or after this instant.
limitinteger · default 50, max 200
events
{
  "data": {
    "reference": "MEDU9091004",
    "events": [
      {
        "type": "departure",
        "status": "actual",
        "description": "Vessel departed",
        "location": "Guayaquil",
        "country": "EC",
        "vesselImo": "9703291",
        "voyage": "514W",
        "occurredAt": "2026-05-04T02:00:00.000Z",
        "recordedAt": "2026-05-04T02:14:11.000Z"
      }
    ]
  },
  "count": 1
}
POST /v1/containers Add to tracking — coming soon

Start tracking a new container. Spends one credit. Polled daily for 30 days from the call timestamp; can be paused or extended via PATCH.

Request body

container_numberstringrequired
4-letter prefix + 7 digits (e.g. MEDU9091004).
shipping_linestring
Optional but recommended; we infer when omitted.
aliasstring
Your internal nickname.
POST
curl -X POST https://broadpath.app/api/v1/containers \
  -H "Authorization: Bearer bp_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "container_number": "MEDU9091004",
    "shipping_line": "MSC",
    "alias": "Q3 reefer #14"
  }'

# 201 Created
GET /v1/vessels/:imo Vessel snapshot

Current AIS snapshot for a vessel by IMO number — position, speed, course, heading, current and next ports.

Returns

imo, mmsi, name, flag, lat, lng, sog, cog, heading, nav_status, destination, last_seen.

vessel
{
  "vessel": {
    "imo": "9703291",
    "mmsi": "636016432",
    "name": "MSC OSCAR",
    "flag": "PA",
    "lat": 30.2,
    "lng": 32.5,
    "sog": 18.2,
    "cog": 145,
    "heading": 147,
    "nav_status": "underway",
    "destination": "SGSIN",
    "last_seen": "2026-05-14T09:30:00.000Z"
  }
}
GET /v1/vessels/:imo/track Historical track

Historical position data, downsampled to a reasonable number of points. Useful for playback, route analysis, dispute evidence.

Query parameters

hoursinteger · default 24, max 8760 (1y)
Lookback window. Long windows are returned downsampled to ~500 points.
pointsinteger · default 500
Max points returned. Capped at 5000.
track
{
  "imo": "9703291",
  "hours": 168,
  "count": 2,
  "points": [
    ["2026-05-07T00:00:00.000Z", 14.2, 78.5, 22.1, 92],
    ["2026-05-08T00:00:00.000Z", 18.6, 64.9, 21.7, 95]
    // [ts, lat, lng, sog, cog]
  ]
}
GET /v1/ports List tracked ports

Search the UN/LOCODE port reference — name, country, and coordinates. Filter by free-text name or 2-letter country code.

Query parameters

qstring
Case-insensitive match on port name.
countrystring · ISO-2
Restrict to one country, e.g. SG.
limitinteger · default 50, max 200
ports
{
  "ports": [
    {"unlocode":"SGSIN", "name":"Singapore", "country":"SG", "lat":1.27, "lng":103.85}
  ],
  "count": 1
}
GET /v1/ports/:unlocode Port detail + nearby vessels

Look up a single port by its UN/LOCODE — name, country, and coordinates.

port
{
  "port": {
    "unlocode": "SGSIN",
    "name": "Singapore",
    "country": "SG",
    "lat": 1.27,
    "lng": 103.85,
    "isPort": true
  }
}

Public endpoints

Unauthenticated reads served at https://broadpath.app/api (no /v1 prefix, no API key). Same data the marketing live-map and air-cargo map consume. Subject to the global 300 req/min per-IP limit.

GET /aircraft Live ADS-B positions · public

Snapshot of every aircraft seen by the OpenSky ingest worker in the last poll cycle (90 s). Returns up to limit rows ordered by recency. Cargo flag is a callsign heuristic across the major all-cargo operators (FedEx, UPS, Atlas, Lufthansa Cargo, Cargolux, …) — best-effort, not authoritative.

Query parameters

limitinteger · default 1500, max 5000
Maximum rows returned.
west, south, east, northnumber · optional
Bounding box in decimal degrees. All four must be present to apply.
cargoOnlyboolean · default false
Restrict to aircraft flagged as cargo by the callsign heuristic.
aircraft
{
  "time": 1779331970,
  "aircraft": [
    {
      "icao24": "4ca7b8",
      "callsign": "GTI521",
      "originCountry": "United States",
      "lat": 50.0341, "lon": 8.5622,
      "baroAltitudeM": 10058,
      "velocityMs": 238.4,
      "trueTrack": 91.7,
      "onGround": false,
      "isCargo": true,
      "lastContact": 1779331960
    }
    // …
  ]
}
GET /awb/:awb Air Waybill lookup · public

Look up a Lufthansa Cargo Air Waybill. Format: NNN-NNNNNNNN — 3-digit airline prefix (Lufthansa is 020) plus 8-digit serial, last digit being the IATA mod-7 check digit. The route accepts 020-12345675, 020 12345675, and bare 02012345675.

Backed by Lufthansa's public Shipment Tracking Platform endpoint. Other airline prefixes are accepted by the parser but typically return isAvailable: false. AWB-level results cached server-side for 10 min.

Returns

awb, airlineCode, serialNumber, isAvailable, shipment (origin, destination, pieces, weight, commodity), flights[], milestones[], raw (upstream passthrough).

Errors

400 INVALID_AWB for a malformed AWB or bad check digit. 502 UPSTREAM_ERROR if Lufthansa's API is unreachable.

awb
{
  "awb": "020-12345675",
  "airlineCode": "020",
  "serialNumber": "12345675",
  "isAvailable": true,
  "shipment": {
    "origin": "FRA",
    "destination": "SIN",
    "pieces": 12,
    "weightKg": 480
  },
  "flights": [
    {"carrierCode":"LH", "flightNumber":"778", "origin":"FRA", "destination":"SIN"}
  ],
  "milestones": [
    {"code":"RCS", "station":"FRA", "at":"2026-05-18T11:20Z"},
    {"code":"DEP", "station":"FRA", "at":"2026-05-18T22:45Z"}
  ]
}
Webhooks

Push, don't pull.

Register an HTTPS endpoint; we send signed POSTs as events happen. Replaces ~95% of the polling people instinctively write.

Event types

  • alerts.createdOne or more shipment alerts fired
  • webhook.testManual test from Settings

An alerts.created body carries event, deliveredAt, account, and an alerts[] array of { type, title, detail, containerId }. More event types are on the roadmap.

Signature

Every POST includes X-Broadpath-Signature: sha256=<hex> — an HMAC-SHA256 of the raw request body, keyed with your signing secret. Verify before processing.

  • AlgorithmHMAC-SHA256 (hex)
  • Delivery idX-Broadpath-Delivery (UUID)
  • Timeout8 sec to respond 2xx
  • PlanBroker

Dedupe on X-Broadpath-Delivery. Recent deliveries and their status are logged in Settings → Webhooks.

Ready to build?

API access is included on the Pro and Broker plans — 120 req/min on Pro, 600 on Broker. Mint a key in Settings and make your first call in minutes.