> ## Documentation Index
> Fetch the complete documentation index at: https://terminal49-sinan-dev-10929-support-initial-shipment-and-per.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive Shipment Status Updates with Webhooks

> Set up Terminal49 webhooks to receive real-time shipment and container status updates, including milestone events, whenever tracking data changes.

In this tutorial, you will register a webhook endpoint and confirm the shape of the status updates Terminal49 sends.

Use webhooks for ongoing tracking updates. Polling is useful for on-demand lookups, but it adds latency and consumes API rate limits.

## Before you start

You need:

* A Terminal49 API key.
* A public HTTPS endpoint that can receive `POST` requests.
* At least one active tracking request.

For local testing, use a temporary endpoint from a tool such as webhook.site. For production, use an endpoint in your own application.

## Create a webhook endpoint

You can create a webhook from the dashboard or the API.

To use the dashboard:

<Steps>
  <Step title="Open Developer Webhooks">
    Go to [Developer Webhooks](https://app.terminal49.com/developers/webhooks) in your Terminal49 dashboard.
  </Step>

  <Step title="Create the endpoint">
    Click **Create Webhook Endpoint** and enter your HTTPS endpoint URL.
  </Step>

  <Step title="Choose events and save">
    Choose the events you want to receive, then save the webhook.
  </Step>
</Steps>

To use the API, send:

```bash theme={null}
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://example.com/webhooks/terminal49",
        "active": true,
        "events": ["tracking_request.succeeded", "container.updated"]
      }
    }
  }'
```

The response includes the webhook `id` and `secret`. Store the `secret` securely; you use it to verify webhook signatures.

## Receive the first event

After Terminal49 detects a change for one of your tracked shipments or containers, it sends a `POST` request to your endpoint.

Every notification has the same top-level shape:

```json theme={null}
{
  "data": {
    "id": "87d4f5e3-df7b-4725-85a3-b80acc572e5d",
    "type": "webhook_notification",
    "attributes": {
      "event": "tracking_request.succeeded",
      "delivery_status": "pending",
      "created_at": "2026-05-11T18:30:00Z"
    }
  },
  "included": []
}
```

Check `data.attributes.event` first. This tells your handler which code path to run.

Common first events are:

* `tracking_request.succeeded`: Terminal49 found the shipment and created tracking records.
* `tracking_request.failed`: Terminal49 could not create tracking for the submitted number.
* `container.updated`: One or more container attributes changed.

## Return a successful response

Your endpoint should return a success status (200, 201, 202, or 204) after it durably accepts the event — persist or enqueue the payload first, then process it asynchronously.

```javascript theme={null}
app.post("/webhooks/terminal49", express.raw({ type: "*/*" }), (req, res) => {
  const payload = JSON.parse(req.body.toString("utf8"));

  queueWebhookForProcessing(payload);

  res.sendStatus(202);
});
```

If Terminal49 receives another response code or the request times out, it retries the notification.

## Before you use webhooks in production

Production webhook handlers should:

1. Verify the `X-T49-Webhook-Signature` header against the raw request body.
2. Allowlist Terminal49 webhook IPs.
3. Deduplicate by `data.id`.
4. Process asynchronously when work may take more than a few seconds.

Follow [Setting up webhooks](/api-docs/in-depth-guides/webhooks) for signature examples and [Webhook Best Practices](/api-docs/webhooks/best-practices) for retry handling.

## Next steps

<CardGroup cols={2}>
  <Card title="Event catalog" icon="list" href="/api-docs/webhooks/event-catalog">
    Choose the events your integration should subscribe to.
  </Card>

  <Card title="Payload reference" icon="brackets-curly" href="/api-docs/webhooks/payloads">
    Review the notification envelope and example payloads.
  </Card>
</CardGroup>
