Skip to main content
This guide will help you get started with Terminal49’s API by walking through the most common workflow: tracking a shipment and receiving status updates. You’ll learn both how to request data and how to receive real-time updates via webhooks.

Prerequisites

Before you begin, you’ll need:
  1. A Terminal49 account - Sign up here if you don’t have one
  2. An API key - Find or create one in your developer portal
  3. A tracking number to monitor:
    • Bill of Lading (BOL) number, Booking number, or Container number
    • The SCAC of the carrier (e.g., MAEU for Maersk)
Don’t have a tracking number? Use our test data: TEST-TR-SUCCEEDED with SCAC TEST for immediate results.

Step 1: Authentication

All API requests require authentication using your API key. Include it in the Authorization header with the prefix Token:
curl -X GET "https://api.terminal49.com/v2/shipments" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/vnd.api+json"
// Node.js with fetch
const headers = {
  'Authorization': `Token ${YOUR_API_KEY}`,
  'Content-Type': 'application/vnd.api+json'
};

const response = await fetch('https://api.terminal49.com/v2/shipments', { headers });

Step 2: Create a Tracking Request

The first step to track a shipment is to create a tracking request. This tells Terminal49 which shipment you want to track. Workflow Example: Start tracking a container to get its ETA
# Using cURL
curl -X POST "https://api.terminal49.com/v2/tracking_requests" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "tracking_request",
      "attributes": {
        "request_type": "bill_of_lading",
        "request_number": "MAEU9736478",
        "scac": "MAEU"
      }
    }
  }'
The response will include a tracking request ID and status:
{
  "data": {
    "id": "b1f30140-c9cb-4354-b8e3-3d92a76289cf",
    "type": "tracking_request",
    "attributes": {
      "request_type": "bill_of_lading",
      "request_number": "MAEU9736478",
      "scac": "MAEU",
      "status": "pending",
      "created_at": "2023-03-16T18:35:42Z",
      "updated_at": "2023-03-16T18:35:42Z"
    },
    "relationships": {
      "tracked_object": {
        "data": null
      }
    }
  }
}
The tracking request starts with status pending. Terminal49 will process it asynchronously, and it will change to succeeded or failed.

Step 3: Check Tracking Request Status (Polling Method)

To check if your tracking request has completed, you can poll the tracking request:
# Using cURL
curl -X GET "https://api.terminal49.com/v2/tracking_requests/b1f30140-c9cb-4354-b8e3-3d92a76289cf" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/vnd.api+json"
When the request succeeds, it will include a relationship to the newly created shipment:
{
  "data": {
    "id": "b1f30140-c9cb-4354-b8e3-3d92a76289cf",
    "type": "tracking_request",
    "attributes": {
      "request_type": "bill_of_lading",
      "request_number": "MAEU9736478",
      "scac": "MAEU",
      "status": "succeeded",
      "created_at": "2023-03-16T18:35:42Z",
      "updated_at": "2023-03-16T18:36:10Z"
    },
    "relationships": {
      "tracked_object": {
        "data": {
          "id": "7a8f8d5e-4c7d-4f8c-9b2a-3c6d8e9f0a1b",
          "type": "shipment"
        }
      }
    }
  }
}

Step 4: Get Shipment Details and ETA

Once the tracking request has succeeded, you can retrieve the shipment and its estimated arrival time:
# Using cURL
curl -X GET "https://api.terminal49.com/v2/shipments/7a8f8d5e-4c7d-4f8c-9b2a-3c6d8e9f0a1b?include=containers" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/vnd.api+json"
The response includes shipment details with the ETA:
{
  "data": {
    "id": "7a8f8d5e-4c7d-4f8c-9b2a-3c6d8e9f0a1b",
    "type": "shipment",
    "attributes": {
      "bill_of_lading_number": "MAEU9736478",
      "booking_number": "123456789",
      "shipping_line_scac": "MAEU",
      "shipping_line_name": "Maersk",
      "estimated_port_arrival_date": "2023-04-15T14:00:00Z",
      "port_of_lading_name": "Shanghai",
      "port_of_lading_locode": "CNSHA",
      "port_of_discharge_name": "Los Angeles",
      "port_of_discharge_locode": "USLAX",
      "vessel_name": "MAERSK SEVILLE",
      "voyage": "243E"
      // ...other attributes
    },
    "relationships": {
      "containers": {
        "data": [
          {
            "id": "e5g4h8i2-4f8c-9b2a-3c6d8e9f0a1b",
            "type": "container"
          }
        ]
      }
    }
  },
  "included": [
    {
      "id": "e5g4h8i2-4f8c-9b2a-3c6d8e9f0a1b",
      "type": "container",
      "attributes": {
        "number": "MAEU1234567",
        "size_type": "40HC",
        "status": "In Transit",
        "location": "At Sea",
        "last_free_day": "2023-04-22T23:59:59Z"
        // ...other attributes
      }
    }
  ]
}

Step 5: Set Up Webhooks for Real-Time Updates (Event-Driven Method)

The Recommended Approach: Instead of constantly polling for updates, use webhooks to receive notifications when events occur.
  1. Set up a webhook endpoint on your server to receive POST requests
  2. Register your webhook with Terminal49:
# Using cURL
curl -X POST "https://api.terminal49.com/v2/webhooks" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "webhook",
      "attributes": {
        "url": "https://your-server.com/webhook",
        "active": true,
        "events": ["*"]
      }
    }
  }'
  1. Implement a webhook handler on your server:
// Node.js with Express
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhook', (req, res) => {
  const event = req.body;

  console.log(`Received event: ${event.data.id}`);
  console.log(`Event type: ${event.type}`);

  // Handle different event types
  if (event.type === 'shipment.estimated_arrival_change') {
    const shipment = event.data;
    console.log(`Shipment ${shipment.attributes.bill_of_lading_number} ETA updated to: ${shipment.attributes.estimated_port_arrival_date}`);

    // Update your database or notify stakeholders
    // ...
  }

  // Always respond with 200 OK to acknowledge receipt
  res.status(200).send('Event received');
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Example Webhook Event: ETA Change

When a shipment’s ETA changes, you’ll receive a webhook event like this:
{
  "type": "shipment.estimated_arrival_change",
  "data": {
    "id": "7a8f8d5e-4c7d-4f8c-9b2a-3c6d8e9f0a1b",
    "type": "shipment",
    "attributes": {
      "bill_of_lading_number": "MAEU9736478",
      "estimated_port_arrival_date": "2023-04-17T16:30:00Z",
      "previous_estimated_port_arrival_date": "2023-04-15T14:00:00Z",
      // ...other attributes
    }
  }
}
Testing Webhooks: Use services like webhook.site or ngrok during development to easily receive and inspect webhook events.

Next Steps

Now that you’ve set up basic tracking and notifications, you can:
  1. Explore Use Cases:
  2. Optimize Your Integration:
  3. Dive Deeper: