Skip to main content

Polling vs. Webhooks in Terminal49

There are two primary methods for getting updates from Terminal49’s API: polling and webhooks. This guide explains both approaches, their trade-offs, and helps you choose the best option for your integration.

Understanding Both Approaches

Polling

Your system periodically makes API requests to check for updates.

Webhooks

Terminal49 proactively sends updates to your system when changes occur.

Polling: The Pull Approach

Polling involves your application regularly querying the Terminal49 API to check for updates on your tracked shipments and containers.
Polling Example
// Example of polling in JavaScript
async function pollForUpdates() {
  try {
    const response = await fetch('https://api.terminal49.com/v2/containers/ABC123', {
      headers: {
        'Authorization': 'Token YOUR_API_KEY'
      }
    });
    const container = await response.json();

    // Process container data
    updateContainerStatus(container);

  } catch (error) {
    console.error('Error polling for updates:', error);
  }
}

// Poll every 15 minutes
setInterval(pollForUpdates, 15 * 60 * 1000);

When to Use Polling

Polling may be easier to implement initially, especially if you’re working with a system that doesn’t support receiving external HTTP requests or if you’re behind a firewall that blocks incoming traffic.
During development or for simple proof-of-concept integrations, polling can be a quick way to get started.
If you only need to check container status once or twice a day, polling might be sufficient.

Disadvantages of Polling

Polling can lead to delayed notifications, excessive API usage, and missed updates if your polling interval is too long.
  • Delayed Updates: You only receive updates when you poll, which could be minutes or hours after an event occurred.
  • Increased API Usage: Frequent polling consumes more API resources.
  • Potential Rate Limiting: Very frequent polling could trigger rate limits.
  • Missed Events: If you poll infrequently, you might miss intermediate state changes.

Webhooks: The Push Approach

Webhooks allow Terminal49 to push real-time updates to your system whenever a change occurs, without you having to ask for them.
Webhook Setup
// Creating a webhook endpoint in Node.js (Express)
const express = require('express');
const app = express();
app.use(express.json());

app.post('/terminal49-webhook', (req, res) => {
  const event = req.body.data.attributes.event;
  const reference = req.body.data.relationships.reference_object.data;

  console.log(`Received ${event} for ${reference.type} ${reference.id}`);

  // Process the webhook notification
  processWebhookEvent(req.body);

  // Always return a success response
  res.status(200).send('Webhook received');
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});
Webhook Registration
// Registering a webhook with Terminal49 API
async function registerWebhook() {
  try {
    const response = await fetch('https://api.terminal49.com/v2/webhooks', {
      method: 'POST',
      headers: {
        'Authorization': 'Token YOUR_API_KEY',
        'Content-Type': 'application/vnd.api+json'
      },
      body: JSON.stringify({
        data: {
          type: "webhook",
          attributes: {
            url: "https://your-domain.com/terminal49-webhook",
            event_types: [
              "container.transport.vessel_arrived",
              "container.transport.vessel_discharged",
              "container.pickup_lfd.changed",
              "tracking_request.succeeded",
              "tracking_request.failed"
            ]
          }
        }
      })
    });

    const webhook = await response.json();
    console.log('Webhook registered:', webhook);

  } catch (error) {
    console.error('Error registering webhook:', error);
  }
}

When to Use Webhooks

If you need immediate notifications about changes (like container arrivals, customs holds, or last free day changes), webhooks are essential.
For production-grade integrations, webhooks provide the most reliable and efficient way to receive updates.
If you’re tracking many containers, webhooks prevent you from having to poll the status of each one repeatedly.

Implementing Webhooks Successfully

For webhooks to work correctly, you need:
  1. A publicly accessible endpoint that can receive HTTP POST requests
  2. Proper webhook handling including:
    • Responding with HTTP 200, 201, 202, or 204 status codes
    • Processing webhook notifications asynchronously when possible
    • Proper error handling and retry logic
  3. Security considerations:
    • Validate the webhook payload
    • Use HTTPS for your endpoint
    • Consider IP filtering if available
During development, you can use tools like ngrok to expose your local development environment to the internet for testing webhooks.
The recommended approach for Terminal49 integration is to:
  1. Primary: Set up webhooks for real-time notifications
  2. Secondary: Implement polling as a fallback to verify data or recover from missed webhooks
Webhook with Polling Fallback
This hybrid approach ensures you get the benefits of real-time updates while having a safety net to verify data integrity.

Example: Hybrid Implementation

Hybrid Approach
// 1. Set up webhooks (primary method)
// See webhook registration example above

// 2. Implement periodic verification (fallback)
async function verifyContainerStatus() {
  // Poll at a much lower frequency (e.g., once per day)
  // to verify data and catch any potentially missed webhooks
  try {
    const response = await fetch('https://api.terminal49.com/v2/containers?filter[updated_since]=24h', {
      headers: {
        'Authorization': 'Token YOUR_API_KEY'
      }
    });

    const data = await response.json();
    const containers = data.data;

    // Verify each container against your local database
    for (const container of containers) {
      verifyContainerData(container);
    }

  } catch (error) {
    console.error('Error verifying container status:', error);
  }
}

// Run verification once per day
setInterval(verifyContainerStatus, 24 * 60 * 60 * 1000);

Summary Comparison

Next Steps