API integrations

Your systems.
Panvaya shipment visibility.

Bring ocean and air tracking into your TMS, ERP or logistics application. Your backend calls our API; Panvaya returns structured shipment data in the same request.

Synchronous REST APIReusable API keyYour field mapping
The integration flowRequest → response

Your TMS / ERP / logistics app

Your backend or integration middleware

↓ POST shipment reference + API key

↑ JSON tracking result or error

Panvaya Logistics API

Ocean milestones · Air cargo · Sailing schedules

Keep your shipment records in your system. Decide which fields to update and when to request the next result.

  1. 01. Configure one reusable key

    Enable the required API products and store your key securely in your backend or middleware.

  2. 02. Send a shipment reference

    Call the Ocean API with a container, B/L or booking, or the Air API with a full AWB.

  3. 03. Receive, map and refresh

    Read the synchronous JSON response, update the matching shipment and call again when needed.

More ways to connect your workflow

Use the API, receive scheduled updates or bring tracking into your existing tools.

Scheduled webhooks

Receive complete Ocean tracking JSON on your schedule through HTTPS with configurable receiver authentication. Manage subscriptions, delivery retries and replay.

Webhook API product access must be enabled for your organization.

Embedded ocean tracking

Add a configurable Ocean tracker to your website or customer portal. Choose approved references, website restrictions and optional private access.

The embedded tracker does not expose your permanent API key.

CSV import & export

Import Ocean or Air shipments into your dashboard from CSV. Export shipment tables for spreadsheets and your own reporting workflows.

Batch upload is included with Premium and Enterprise.

Need a webhook for a specific event change? Contact support to discuss your requirements.

Email reports & shipment alerts

Enable daily Ocean shipment reports by email. Review shipment exceptions and risk alerts in your dashboard.

More logistics data through the same API

Product access and usage credits apply

Use JSON responses or exported CSV files in your own reporting pipeline. Available fields depend on the product and source; emissions outputs are estimates.

Integration starter kit

Download API field mappings, a Postman collection and a webhook receiver example for your implementation.

Set credentials locally. Postman live calls are disabled until you enable them and can consume credits. The receiver is a local inbox example; adapt it to your production hosting and shipment workflow.

Built for your data model

From tracking reference to shipment fields

Choose a reference to explore our request, response and suggested mappings.

Developer portal
Full API documentation

01 Your backend calls Panvaya

curl -X POST "https://api.panvaya.com/api/v1/track/ocean" \
  -H "X-API-Key: YOUR_PANVAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "container": "MEDU8611713",
  "shipping_line_scac": "MSCU"
}'

JavaScript and Python read PANVAYA_API_KEY from your server environment.

02 Map the JSON response

Illustrative 200 OK · response excerpt
{
  "data": {
    "reference": {
      "number": "MEDU8611713",
      "type": "container"
    },
    "shipping_line": {
      "scac": "MSCU",
      "name": "Mediterranean Shipping Company (MSC)"
    },
    "status": "in_transit",
    "journey": {
      "origin": null,
      "port_of_lading": {
        "location_id": 1,
        "estimated_departure_at": "2026-10-24T00:00:00",
        "actual_departure_at": null,
        "estimated_arrival_at": null,
        "actual_arrival_at": null
      },
      "port_of_discharge": {
        "location_id": 3,
        "estimated_departure_at": null,
        "actual_departure_at": null,
        "estimated_arrival_at": "2026-11-11T00:00:00",
        "actual_arrival_at": null
      },
      "destination": null
    },
    "locations": [
      {
        "id": 1,
        "name": "Montreal",
        "state": "QC",
        "country": "Canada",
        "country_code": "CA",
        "locode": "CAMTR",
        "latitude": 45.545,
        "longitude": -73.528,
        "timezone": "America/Toronto"
      },
      {
        "id": 2,
        "name": "Gioia Tauro",
        "state": null,
        "country": "Italy",
        "country_code": "IT",
        "locode": "ITGIT",
        "latitude": 38.442,
        "longitude": 15.902,
        "timezone": "Europe/Rome"
      },
      {
        "id": 3,
        "name": "Mersin",
        "state": "33",
        "country": "Türkiye",
        "country_code": "TR",
        "locode": "TRMER",
        "latitude": 36.798,
        "longitude": 34.642,
        "timezone": "Europe/Istanbul"
      }
    ],
    "transports": [
      {
        "id": 1,
        "mode": "truck",
        "name": null,
        "imo": null,
        "call_sign": null,
        "mmsi": null,
        "flag": null,
        "vehicle_number": null,
        "voyage_number": null
      },
      {
        "id": 2,
        "mode": "vessel",
        "name": "MSC KILIMANJARO IV",
        "imo": 9318175,
        "call_sign": "A8JX3",
        "mmsi": 636013001,
        "flag": "LR",
        "vehicle_number": null,
        "voyage_number": "CD643R"
      },
      {
        "id": 3,
        "mode": "vessel",
        "name": "MSC PAMIRA III",
        "imo": 9239903,
        "call_sign": "5LCZ6",
        "mmsi": 636021246,
        "flag": "MH",
        "vehicle_number": null,
        "voyage_number": "AH645R"
      }
    ],
    "containers": [
      {
        "number": "MEDU8611713",
        "equipment": {
          "carrier_code": "40 HIGH CUBE",
          "iso_code": "45G1",
          "description": "High Cube Dry Standard",
          "size": 40,
          "length": "40'",
          "height": "9'6''",
          "width": "8'",
          "bulk": false,
          "liquid": false,
          "reefer": false,
          "high_cube": true,
          "dry": true
        },
        "status": "in_transit",
        "events": [
          {
            "id": 1,
            "location_id": 1,
            "event_code": "PICK",
            "event_name": "Empty equipment picked up",
            "event_category": "equipment",
            "carrier_event_name": "Start Export Cycle",
            "event_time": "2026-10-14T00:00:00",
            "actual": true,
            "transport_id": 1
          },
          {
            "id": 2,
            "location_id": 1,
            "event_code": "GTIN",
            "event_name": "Gate in",
            "event_category": "equipment",
            "carrier_event_name": "Export received at CY",
            "event_time": "2026-10-16T00:00:00",
            "actual": true,
            "transport_id": 1
          },
          {
            "id": 3,
            "location_id": 1,
            "event_code": "DEPA",
            "event_name": "Vessel departed",
            "event_category": "transport",
            "carrier_event_name": "Estimated Time of Departure",
            "event_time": "2026-10-24T00:00:00",
            "actual": false,
            "transport_id": 2
          },
          {
            "id": 4,
            "location_id": 2,
            "event_code": "DISC",
            "event_name": "Discharged at transshipment port",
            "event_category": "equipment",
            "carrier_event_name": "Full Intended Transshipment",
            "event_time": "2026-11-07T00:00:00",
            "actual": false,
            "transport_id": 2
          },
          {
            "id": 5,
            "location_id": 2,
            "event_code": "LOAD",
            "event_name": "Loaded at transshipment port",
            "event_category": "equipment",
            "carrier_event_name": "Full Intended Transshipment",
            "event_time": "2026-11-07T00:00:00",
            "actual": false,
            "transport_id": 3
          },
          {
            "id": 6,
            "location_id": 3,
            "event_code": "ARRI",
            "event_name": "Vessel arrived",
            "event_category": "transport",
            "carrier_event_name": "Estimated Time of Arrival",
            "event_time": "2026-11-11T00:00:00",
            "actual": false,
            "transport_id": 3
          }
        ]
      }
    ]
  },
  "errors": null
}

Excerpt from our developer example. Static sample; live data and availability vary. Optional route geometry is omitted. These examples do not send API requests.

Field mapping guide

Ocean response

Suggested destination fields for your TMS, ERP or logistics app. Exact field names and required fields depend on your system and configuration.

Panvaya Container fields and suggested application mappings
Your application fieldPanvaya response fieldsMapping guidance
Tracking reference & carrier
data.reference.numberdata.reference.typedata.shipping_line.scac
Match the queried reference and carrier to your shipment. Keep your own order, PO and shipment IDs in your application.
Container records & status
data.containers[].numberdata.containers[].statusdata.status
Create or update each returned container separately. Map shipment and container statuses to your own status vocabulary.
Load & discharge ports
data.journey.port_of_lading.location_iddata.journey.port_of_discharge.location_iddata.locations[].iddata.locations[].locode
Resolve each location_id against locations[].id to get the port UN/LOCODE. Lookup IDs are local to this response, not permanent port identifiers.
Departure & arrival dates
data.journey.port_of_lading.estimated_departure_atdata.journey.port_of_lading.actual_departure_atdata.journey.port_of_discharge.estimated_arrival_atdata.journey.port_of_discharge.actual_arrival_at
Map ETD, ATD, ETA and ATA separately. A missing actual date stays null; an estimate is not proof of departure or arrival.
Milestone history
data.containers[].events[].event_codedata.containers[].events[].event_timedata.containers[].events[].actual
Map canonical event codes into your milestone model. Preserve actual versus planned and source date precision; do not append duplicates on each refresh.
Event place & timezone
data.containers[].events[].location_iddata.locations[].namedata.locations[].timezone
Resolve the event location within this response. Preserve timezone and date-only precision; do not assume a timestamp without an offset is UTC.
Vessel & voyage
data.containers[].events[].transport_iddata.transports[].iddata.transports[].modedata.transports[].namedata.transports[].imodata.transports[].voyage_number
Resolve each event's transport_id. Use vessel fields only for vessel movements and retain each voyage when the journey changes ships.
Equipment type
data.containers[].equipment.iso_codedata.containers[].equipment.description
Map equipment on the matching container. Carrier-supplied details may be missing; leave unavailable values empty.

[] means each item in an array. Fields depend on carrier availability. Preserve missing data rather than inventing a value.

Prepare your integration

  • Keep credentials server-side. Generate once, reuse securely and rotate when needed. Never put the API key in a browser, mobile bundle or public code.
  • Handle outcomes explicitly. Correct invalid input, retain existing shipment data on errors, respect Retry-After on 429 responses and use bounded backoff for transient failures.
  • Control refresh frequency. Responses may use cached tracking data. Successful calls, including cache hits, use credits; product access and organization limits apply.

Bring your application requirements

For a mapping review, share your TMS or ERP name and version, a redacted target schema, required fields, milestone codes, shipment matching rules and expected refresh volume.

Your internal order IDs, PO numbers and business workflow remain yours. Our stateless tracking API does not automatically create dashboard shipments or write into your ERP.

Integration questions, answered

Does Panvaya provide native TMS or ERP connectors?

Your team or integration partner connects your backend or middleware through our REST APIs or scheduled Ocean webhooks, then maps the returned JSON to your system. Embedded tracking and dashboard CSV tools offer other ways to use Panvaya. No native vendor connector, marketplace app or platform partnership is implied.

Do we need a new API key for every request?

No. Generate a key once in your API dashboard, save it securely on your backend and reuse it in the X-API-Key header. The secret is shown only at creation. Replace it when rotated, revoked or expired; product access, credits and rate limits still apply.

Is each response synchronous, and how fresh is the data?

Yes. Each tracking call returns its result or error in the same HTTP request. Results use Panvaya's tracking pipeline and shared caches; they do not guarantee a new carrier fetch on every call. Freshness and response time depend on the carrier and cache. Your application decides when to request another update.

Can we track a bill of lading with several containers?

Yes, where the carrier supports it. Send the bol reference to the Ocean endpoint and process every returned item in data.containers. You can also scope a supported B/L or booking request with a container number. Do not copy one container's milestones onto another.