Skip to main content

Documentation Index

Fetch the complete documentation index at: https://terminal49-codex-docs-audit-diataxis-skill.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

In this tutorial, you will list the shipment and container records created from your tracking requests. Use this step after you have created at least one tracking request.

Shipment and container data in Terminal49

After Terminal49 accepts a tracking request, it starts collecting available data from carriers and terminals. You can retrieve the latest stored data at any time with the Shipments and Containers endpoints. Use these endpoints for on-demand lookups. For ongoing status monitoring, use webhooks instead of polling.

List all your tracked shipments

If your tracking request was successful, you will now be able to list your tracked shipments. Replace YOUR_API_KEY with your API key. Sometimes it takes a few minutes for a new tracking request to appear as a shipment. Copy the response into a text editor so you can inspect it while continuing the tutorial.
http
{
  "method": "get",
  "url": "https://api.terminal49.com/v2/shipments",
  "headers": {
    "Content-Type": "application/vnd.api+json",
    "Authorization": "Token YOUR_API_KEY"
  }
}

Why so much JSON? (A note on JSON:API)

The Terminal49 API is JSON:API compliant. JSON:API libraries can translate the response into a full object model compatible with an ORM, which is powerful but produces larger, more structured payloads. If you parse JSON directly, this can feel verbose. For production use, consider adopting a JSON:API client library to get the most out of the format. For this tutorial, you will work with the data directly.

Authentication

The API uses a Token-prefixed API key in the Authorization header. Send your API key with each request in this format:
Authorization: Token YOUR_API_KEY
Webhooks are associated with API tokens, which is how Terminal49 identifies which account to send shipment updates to.

Inspect the shipment response

The /shipments response returns an array of shipment objects. Each shipment includes attributes, relationships to related records, and a self link. For clarity, some fields have been replaced with ellipses (…) and key areas are bolded. The data attribute contains an array of objects. Each object is of type shipment and includes attributes such as bill of lading number and port of lading. Each shipment object also has relationships to structured data objects like ports and terminals, as well as a list of containers on the shipment. You can access these structured elements through the API. Terminal49 cleans and enhances the data from the shipping line, so you get a pre-defined object for each port, terminal, and other entity.
{
  "data": [
    {
      /*  this is an internal id that you can use to query the API directly, i.e by hitting https://api.terminal49.com/v2/shipments/123456789 */
      "id": "123456789",
      // the object type is a shipment, per below.
      "type": "shipment",
      "attributes": {
        // Your BOL number that you used in the tracking request
        "bill_of_lading_number": "99999999",
        ...
        "shipping_line_scac": "MAEU",
        "shipping_line_name": "Maersk",
        "port_of_lading_locode": "INVTZ",
        "port_of_lading_name": "Visakhapatnam",
        ...
      },
      "relationships": {

        "port_of_lading": {
          "data": {
            "id": "bde5465a-1160-4fde-a026-74df9c362f65",
            "type": "port"
          }
        },
        "port_of_discharge": {
          "data": {
            "id": "3d892622-def8-4155-94c5-91d91dc42219",
            "type": "port"
          }
        },
        "pod_terminal": {
          "data": {
            "id": "99e1f6ba-a514-4355-8517-b4720bdc5f33",
            "type": "terminal"
          }
        },
        "destination": {
          "data": null
        },
        "containers": {
          "data": [
            {
              "id": "593f3782-cc24-46a9-a6ce-b2f1dbf3b6b9",
              "type": "container"
            }
          ]
        }
      },
      "links": {
        // this is a link to this specific shipment in the API.   
        "self": "/v2/shipments/7f8c52b2-c255-4252-8a82-f279061fc847"
      }
    },
    ...
    ],
  ...
}

Sample code: listing tracked shipments in a Google Sheet

Below is code written in Google App Script that lists the current shipments into the current sheet of a spreadsheet. App Script is very similar to Javascript. Because Google App Script does not have native JSON API support, you need to parse the JSON directly, making this example an ideal real world application of the API.

function listTrackedShipments(){
  // first we construct the request.
  var options = {
    "method" : "GET",
    "headers" : {
      "content-type": "application/vnd.api+json",
      "authorization" : "Token YOUR_API_KEY"
    },
      "payload" : ""
   };


  try {
    // note that URLFetchApp is a function of Google App Script, not a standard JS function.
    var response = UrlFetchApp.fetch("https://api.terminal49.com/v2/shipments", options);
    var json = response.getContentText();
    var shipments = JSON.parse(json)["data"];
    var shipment_values = [];
    shipment_values = extractShipmentValues(shipments);
    listShipmentValues(shipment_values);
  } catch (error){
    //In JS you would use console.log(), but App Script uses Logger.log().
    Logger.log("error communicating with t49 / shipments: " + error);
  }
}


function extractShipmentValues(shipments){
  var shipment_values = [];
  shipments.forEach(function(shipment){
      // iterating through the shipments.
    shipment_values.push(extractShipmentData(shipment));
  });
  return shipment_values;
}

function extractShipmentData(shipment){
   var shipment_val = [];
   //for each shipment I'm extracting some of the key info i want to display.
   shipment_val.push(shipment["attributes"]["shipping_line_scac"],
                      shipment["attributes"]["shipping_line_name"],
                      shipment["attributes"]["bill_of_lading_number"],
                      shipment["attributes"]["pod_vessel_name"],  
                      shipment["attributes"]["port_of_lading_name"],
                      shipment["attributes"]["pol_etd_at"],
                      shipment["attributes"]["pol_atd_at"],
                      shipment["attributes"]["port_of_discharge_name"],
                      shipment["attributes"]["pod_eta_at"],
                      shipment["attributes"]["pod_ata_at"],
                      shipment["relationships"]["containers"]["data"].length,
                      shipment["id"]
                    );
  return shipment_val;
}


function listShipmentValues(shipment_values){
// now, list the data in the spreadsheet.
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var homesheet =   ss.getActiveSheet();
  var STARTING_ROW = 1;
  var MAX_TRACKED = 500;  
  try {
    // clear the contents of the sheet first. 
    homesheet.getRange(STARTING_ROW,1,MAX_TRACKED,shipment_values[0].length).clearContent();
    // now insert all the shipment values directly into the sheet.
    homesheet.getRange(STARTING_ROW,1,shipment_values.length,shipment_values[0].length).setValues(shipment_values);
  } catch (error){
    Logger.log("there was an error in listShipmentValues: " + error);
  }
}

List all your tracked containers

You can also list out all of your Containers. Container data includes terminal availability, last free day, holds, fees, and other logistical information that you might use for drayage operations at port.
To learn how to use holds and fees data to determine if a container is ready for pickup, see Container Holds, Fees, and Release Readiness.
Try it below. Click “Headers” and replace YOUR_API_KEY with your API key. We suggest copy and pasting the response returned into a text editor so you can examine it while continuing the tutorial.
http
{
  "method": "get",
  "url": "https://api.terminal49.com/v2/containers",
  "headers": {
    "Content-Type": "application/vnd.api+json",
    "Authorization": "Token YOUR_API_KEY"
  }
}

Anatomy of containers JSON response

Now that you’ve got a list of containers, let’s examine the response you’ve received.
// We have an array of objects in the data returned.
  "data": [
    {
      //
      "id": "internalid",
      // this object is of type Container.
      "type": "container",
      "attributes": {

        // Here is your container number
        "number": "OOLU-xxxx",
        // Seal Numbers aren't always returned by the carrier.
        "seal_number": null,
        "created_at": "2020-09-13T19:16:47Z",
        "equipment_type": "reefer",
        "equipment_length": null,
        "equipment_height": null,
        "weight_in_lbs": 54807,

        "fees_at_pod_terminal": [],
        "holds_at_pod_terminal": [],
        // here is your last free day.
        "pickup_lfd": "2020-09-17T07:00:00Z",
        "pickup_appointment_at": null,
        "availability_known": true,
        "available_for_pickup": false,
        "pod_arrived_at": "2020-09-13T22:05:00Z",
        "pod_discharged_at": "2020-09-15T05:27:00Z",
        "location_at_pod_terminal": "CC1-162-B-3(Deck)",
        "final_destination_full_out_at": null,
        "pod_full_out_at": "2020-09-18T10:30:00Z",
        "empty_terminated_at": null
      },
      "relationships": {
        // linking back to the shipment object, found above.
        "shipment": {
          "data": {
            "id": "894befec-e7e2-4e48-ab97-xxxxxxxxx",
            "type": "shipment"
          }
        },
        "pod_terminal": {
          "data": {
            "id": "39d09f18-cf98-445b-b6dc-xxxxxxxxx",
            "type": "terminal"
          }
        },
        ...
      }
    },
    ...