Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/api-docs/getting-started/receive-status-updates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ To use the dashboard:
<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 title="Select events and save">
Select the events you want to receive, then save the webhook.
</Step>
</Steps>

Expand Down Expand Up @@ -124,7 +124,7 @@ Follow [Setting up webhooks](/api-docs/in-depth-guides/webhooks) for signature e

<CardGroup cols={2}>
<Card title="Event catalog" icon="list" href="/api-docs/webhooks/event-catalog">
Choose the events your integration should subscribe to.
Select 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ To check a single request, append the `id` from the create response: `GET /v2/tr
<Warning>
**Tracking request troubleshooting**

The most common issue people encounter is that they are entering the wrong number.
The most common issue is entering the wrong number.

Check that you are entering a Bill of Lading number, booking number, or container number — not an internal reference from your company or freight forwarder. Verify the number by going to the carrier's website and tracking the shipment with it. If that works and the SCAC is supported by Terminal49, you should be able to track it through the API.

Expand Down
12 changes: 6 additions & 6 deletions docs/api-docs/in-depth-guides/auto-detect-carrier.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ Submit any tracking number, and the API returns:
<Step title="You submit a tracking number" icon="input-text">
Just the number — no need to specify the shipping line or type
</Step>
<Step title="We analyze the pattern" icon="microchip-ai">
Our system uses machine learning and historical data from millions of
<Step title="Terminal49 analyzes the pattern" icon="microchip-ai">
Terminal49 uses machine learning and historical data from millions of
shipments to predict the shipping line.
</Step>
<Step title="You get the SCAC and confidence score" icon="bullseye-arrow">
Expand All @@ -74,7 +74,7 @@ Submit any tracking number, and the API returns:
<Tab title="Container Number" icon="box">
Container numbers follow the ISO 6346 format. While the first three letters (owner code) often indicate the owner, the container might be moved by a different shipping line (VOCC).

Our system analyzes the number against tens of millions of historical records to predict which shipping line is moving the container.
Terminal49 analyzes the number against tens of millions of historical records to predict which shipping line is moving the container.

**Example Input:** `MSCU1234567`

Expand Down Expand Up @@ -278,7 +278,7 @@ Submit any tracking number, and the API returns:
## Understanding the response

<AccordionGroup>
<Accordion title="Decision Types Explained" icon="code-branch" defaultOpen>
<Accordion title="Decision types explained" icon="code-branch" defaultOpen>
The `decision` field tells you how confident the prediction is and what action to take:

| Decision | When it's used | What to do |
Expand All @@ -295,7 +295,7 @@ Submit any tracking number, and the API returns:

</Accordion>

<Accordion title="Validation Fields" icon="shield-check">
<Accordion title="Validation fields" icon="shield-check">
The API validates numbers before returning predictions:

| Field | Description |
Expand All @@ -311,7 +311,7 @@ Submit any tracking number, and the API returns:

</Accordion>

<Accordion title="Full Response Schema" icon="brackets-curly">
<Accordion title="Full response schema" icon="brackets-curly">
| Field | Type | Description |
| ----- | ---- | ----------- |
| `number_type` | string | Detected type: `container`, `bill_of_lading`, or `booking` |
Expand Down
2 changes: 1 addition & 1 deletion docs/api-docs/in-depth-guides/event-timestamps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ then the local time of the `pod_arrived_at` timestamp would be `2022-12-22T07:00
On transport events, both `location_locode` (and any related `location` object) are nullable. They may be `null` when:

- The event is **estimated** (`estimated: true`) and the carrier does not publish a location for the prediction.
- The carrier or data provider omits the location field on a given event — this varies by carrier and event type.
- The carrier or data provider omits the location field on a given event. This varies by carrier and event type.
- Terminal49 could not normalize the source location to a known UNLOCODE.

This is expected behavior, not a delivery error. The location is not back-filled later for the same event — if a subsequent actual event (for example, `container.transport.vessel_arrived` replacing `container.transport.estimated.vessel_arrived`) includes a location, it will be delivered as a new event. Treat `location_locode == null` as "location unknown" rather than waiting for an update on the original event.
Expand Down
6 changes: 3 additions & 3 deletions docs/api-docs/in-depth-guides/holds-and-fees.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Each item in `holds_at_pod_terminal` is a `terminal_hold` object:
| `status` | string | `"hold"` or `"pending"` |
| `description` | string \| null | Raw text from the terminal, if provided |

When a hold is cleared, the object is removed from the array entirely. There is no `"released"` status — an empty array means no active holds.
When a hold is cleared, the object is removed from the array entirely. There is no `"released"` status. An empty array means no active holds.

| Hold name | Description | Who resolves it |
|-----------|-------------|-----------------|
Expand Down Expand Up @@ -454,11 +454,11 @@ const totalAmount = lineItems.reduce((acc, f) => acc + f.amount, 0);
</Accordion>

<Accordion title="Can a container have holds and fees at the same time?">
Yes. Holds and fees are independent. Holds block pickup — your container cannot be released until all holds are cleared. Fees are charges you owe (demurrage, exam costs, etc.) that may continue accruing whether or not holds are present.
Yes. Holds and fees are independent. Holds block pickup. Your container cannot be released until all holds are cleared. Fees are charges you owe (demurrage, exam costs, etc.) that may continue accruing whether or not holds are present.
</Accordion>

<Accordion title="What happens when a hold is cleared?">
The hold object is removed from the `holds_at_pod_terminal` array entirely. There is no `"released"` status — an empty array means no active holds. You receive a `container.updated` webhook when this happens.
The hold object is removed from the `holds_at_pod_terminal` array entirely. There is no `"released"` status. An empty array means no active holds. You receive a `container.updated` webhook when this happens.
</Accordion>

<Accordion title="Why does available_for_pickup say false when there are no holds?">
Expand Down
2 changes: 1 addition & 1 deletion docs/api-docs/in-depth-guides/mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Before you begin, make sure you have:
Only the [local stdio server](#local-stdio-development) reads the `T49_API_TOKEN` environment variable instead of a header.

<Tip>
For hosted production usage, connect to `https://mcp.terminal49.com` — the root origin is the canonical connector URL and OAuth resource identifier.
For hosted production usage, connect to `https://mcp.terminal49.com`. The root origin is the canonical connector URL and OAuth resource identifier.
</Tip>

---
Expand Down
4 changes: 2 additions & 2 deletions docs/api-docs/in-depth-guides/rail-integration-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Integrate these notifications by subscribing to the webhooks and handling the in

#### Set up a webhook for rail events

Rail events use the same webhook infrastructure as ocean events — there is no separate rail-only endpoint or configuration. Create one webhook and subscribe it to the rail events you care about.
Rail events use the same webhook infrastructure as ocean events. There is no separate rail-only endpoint or configuration. Create one webhook and subscribe it to the rail events you care about.

You can create a webhook either from the [Developer Webhooks](https://app.terminal49.com/developers/webhooks) page in the dashboard or by calling [`POST /webhooks`](/api-docs/api-reference/webhooks/create-a-webhook) with the rail events in the `events` array:

Expand Down Expand Up @@ -197,7 +197,7 @@ The container's top-level `pickup_lfd` attribute is a coalesced value derived fr
2. `import_deadlines.pickup_lfd_terminal` — LFD from the POD terminal (timezone: `pod_timezone`).
3. `import_deadlines.pickup_lfd_rail` — LFD from the rail carrier at the inland destination (timezone: `final_destination_timezone`).

For rail moves, subscribe to the `container.pickup_lfd_rail.changed` webhook to be notified when the rail carrier updates the inland LFD. The legacy `ind_facility_lfd_on` field is deprecated — read `import_deadlines.pickup_lfd_rail` instead.
For rail moves, subscribe to the `container.pickup_lfd_rail.changed` webhook to be notified when the rail carrier updates the inland LFD. The legacy `ind_facility_lfd_on` field is deprecated. Read `import_deadlines.pickup_lfd_rail` instead.

{/* TODO: Look at the other container attributes that could be fed via rail but are currently shipping-line-only. Such as :current_issues, :pickup_appointment_at, :availability_known, :available_for_pickup */}

Expand Down
24 changes: 12 additions & 12 deletions docs/api-docs/in-depth-guides/routing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ curl --request GET \

The response is a standard GeoJSON FeatureCollection that can be directly used with most mapping libraries (Leaflet, Mapbox GL, Google Maps, etc.).

<Accordion title="Example Response Overview">
<Accordion title="Example response overview">
```json
{
"type": "FeatureCollection",
Expand Down Expand Up @@ -138,7 +138,7 @@ Geometry Type: `Point`

Port features represent all ports in the container's route: the port of lading (POL), port of discharge (POD), and any transshipment ports (TS1, TS2, etc.).

<Accordion title="Port Feature Example">
<Accordion title="Port feature example">
```json
{
"type": "Feature",
Expand Down Expand Up @@ -172,7 +172,7 @@ Port features represent all ports in the container's route: the port of lading (
```
</Accordion>

<Accordion title="Port Feature Properties">
<Accordion title="Port feature properties">
| Property | Type | Description |
|----------|------|-------------|
| `feature_type` | string | Always `"port"` |
Expand Down Expand Up @@ -200,7 +200,7 @@ Geometry Type: `Point`

This feature is only present when the container is currently on a vessel at sea. It represents the vessel's current position.

<Accordion title="Current Vessel Feature Example">
<Accordion title="Current vessel feature example">
```json
{
"type": "Feature",
Expand Down Expand Up @@ -244,7 +244,7 @@ This feature is only present when the container is currently on a vessel at sea.
```
</Accordion>

<Accordion title="Current Vessel Feature Properties">
<Accordion title="Current vessel feature properties">
| Property | Type | Description |
|----------|------|-------------|
| `feature_type` | string | Always `"current_vessel"` |
Expand Down Expand Up @@ -282,7 +282,7 @@ Geometry Type: `LineString`

These features represent the actual historical paths taken by vessels for completed and in-progress legs of the journey. Each LineString contains a series of coordinates showing where the vessel traveled between two ports.

<Accordion title="Past Vessel Locations Feature Example">
<Accordion title="Past vessel locations feature example">
```json
{
"type": "Feature",
Expand Down Expand Up @@ -319,7 +319,7 @@ These features represent the actual historical paths taken by vessels for comple
```
</Accordion>

<Accordion title="Past Vessel Locations Properties">
<Accordion title="Past vessel locations properties">
| Property | Type | Description |
|----------|------|-------------|
| `feature_type` | string | Always `"past_vessel_locations"` |
Expand All @@ -339,7 +339,7 @@ Geometry Type: `LineString`

These features represent predicted vessel paths for future legs that have not yet started. The LineString shows the estimated route between two ports.

<Accordion title="Estimated Full Leg Feature Example">
<Accordion title="Estimated full leg feature example">
```json
{
"type": "Feature",
Expand All @@ -364,7 +364,7 @@ These features represent predicted vessel paths for future legs that have not ye
```
</Accordion>

<Accordion title="Estimated Full Leg Properties">
<Accordion title="Estimated full leg properties">
| Property | Type | Description |
|----------|------|-------------|
| `feature_type` | string | Always `"estimated_full_legs"` |
Expand All @@ -380,7 +380,7 @@ Geometry Type: `LineString`

This feature represents the predicted path from the vessel's current position to the next port. It is only present when the container is currently on a vessel at sea.

<Accordion title="Estimated Partial Leg Feature Example">
<Accordion title="Estimated partial leg feature example">
```json
{
"type": "Feature",
Expand Down Expand Up @@ -413,7 +413,7 @@ This feature represents the predicted path from the vessel's current position to
```
</Accordion>

<Accordion title="Estimated Partial Leg Properties">
<Accordion title="Estimated partial leg properties">
| Property | Type | Description |
|----------|------|-------------|
| `feature_type` | string | Always `"estimated_partial_leg"` |
Expand Down Expand Up @@ -444,7 +444,7 @@ To visualize a container's journey using the GeoJSON response on your own map (s
- Display vessel information (name, IMO, speed, heading) for the current vessel
- Show leg information (departure/arrival times, vessel ID) for path segments

<Accordion title="Example: Using Leaflet.js">
<Accordion title="Example: using Leaflet.js">
```javascript
// Fetch the GeoJSON data
fetch('https://api.terminal49.com/v2/containers/{id}/map_geojson', {
Expand Down
2 changes: 1 addition & 1 deletion docs/api-docs/in-depth-guides/terminal49-map.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The following examples pass `containerId` and `shipmentId` variables to the embe
They relate to `id` attributes of the container and shipment objects that are returned by the API.

<Note>
The map embed works from a local development environment. Open your HTML file directly in a browser or serve it from `http://localhost` — there is no domain allowlisting on the embed itself. Your page just needs internet access to load `bundle.js` and `bundle.css` from `https://map.terminal49.com`, and a valid publishable API key.
The map embed works from a local development environment. Open your HTML file directly in a browser or serve it from `http://localhost`. There is no domain allowlisting on the embed itself. Your page just needs internet access to load `bundle.js` and `bundle.css` from `https://map.terminal49.com`, and a valid publishable API key.
</Note>

## Embed the map on your website
Expand Down
6 changes: 3 additions & 3 deletions docs/api-docs/in-depth-guides/tracking-request-lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ When you submit a tracking request, your request is added to a queue to be check

If Terminal49 has difficulty connecting to the shipping line or cannot parse the response, it retries up to 14 times.

This process can take up to approximately 24 hours. You will not receive a `tracking_request.failed` webhook notification until Terminal49 has exhausted the retries, and the `status` field will not be changed to `failed` until then.
This process can take up to approximately 24 hours. You will not receive a `tracking_request.failed` webhook notification until Terminal49 has exhausted the retries, and Terminal49 does not change the `status` field to `failed` until then.

## Request number not found / awaiting manifest

Expand Down Expand Up @@ -71,15 +71,15 @@ Terminal49 will stop tracking requests for the following reasons:
- More than 56 days have passed since the shipment arrived at its destination.
- There have been no updates from the shipping line for more than 56 days.

In addition end-users may stop tracking a shipment through the dashboard.
You can also stop tracking a shipment from the dashboard.

### Stopping tracking programmatically

Tracking is stopped at the **shipment level**, not on the tracking request or on an individual container. Use [Stop tracking a shipment](/api-docs/api-reference/shipments/stop-tracking-shipment) (`PATCH /shipments/{id}/stop_tracking`).

- A tracking request initiates tracking and can create a shipment. Once the shipment exists, the shipment is the resource you manage.
- There is no `DELETE` or "stop" endpoint on the `tracking_requests` resource. The tracking request `status` reflects the request outcome (`pending`, `created`, `failed`, `tracking_stopped`); the shipment is where active tracking is stopped or resumed.
- Stopping a shipment stops tracking for **all containers on that shipment**. There is no per-container stop endpoint — this behavior is the same whether the shipment was originally tracked by bill of lading, booking, or container number.
- Stopping a shipment stops tracking for **all containers on that shipment**. There is no per-container stop endpoint. This behavior is the same whether the shipment was originally tracked by bill of lading, booking, or container number.
- To resume, use [Resume tracking a shipment](/api-docs/api-reference/shipments/resume-tracking-shipment).

## Retrieving status
Expand Down
2 changes: 1 addition & 1 deletion docs/api-docs/in-depth-guides/webhooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Subscribe only to the events your integration handles. Use the [Event Catalog](/

The webhook response includes a `secret` attribute. Store it in your secrets manager.

Terminal49 signs every webhook delivery with an HMAC SHA-256 digest of the raw request body. The digest is sent in the `X-T49-Webhook-Signature` header.
Terminal49 signs every webhook delivery with an HMAC SHA-256 digest of the raw request body and sends the digest in the `X-T49-Webhook-Signature` header.

## Verify the signature

Expand Down
4 changes: 2 additions & 2 deletions docs/api-docs/webhooks/best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ app.post("/webhooks/terminal49", async (req, res) => {
});
```

If you acknowledge before storing the event and your process crashes mid-handling, the notification is lost Terminal49 sees a success response and does not retry.
If you acknowledge before storing the event and your process crashes mid-handling, the notification is lost. Terminal49 sees a success response and does not retry.

Any other response — including a timeout — triggers retries. If your endpoint consistently fails, Terminal49 retries up to 12 times before marking the notification as failed.

Expand Down Expand Up @@ -118,7 +118,7 @@ The Trigger endpoint sends an example payload for the event you choose. If you i
If your endpoint goes down, Terminal49 retries failed deliveries. When your endpoint recovers:

1. Use the [Webhook Notifications API](/api-docs/api-reference/webhook-notifications/list-webhook-notifications) to list recent notifications and identify the ones with `delivery_status: failed`.
2. Re-fetch the current state of the affected shipments and containers from the REST API. Webhook notifications cannot be replayed — the [Trigger Webhook](/api-docs/api-reference/webhooks/trigger-a-webhook) endpoint only sends a one-time sample payload for testing.
2. Re-fetch the current state of the affected shipments and containers from the REST API. Webhook notifications cannot be replayed. The [Trigger Webhook](/api-docs/api-reference/webhooks/trigger-a-webhook) endpoint only sends a one-time sample payload for testing.
3. For longer outages, list recent shipments via the API to catch up on any missed state changes.

### Recover events you were never subscribed to
Expand Down
2 changes: 1 addition & 1 deletion docs/datasync/home.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ If any of the details of your shipment or containers change (for example, if the
- If you're using DataSync, Terminal49 updates the data in your system
- If you're using the API, Terminal49 posts the shipment to the webhook you provide

👈🏽 Please click API Docs or DataSync on the left to get started!
👈🏽 Select API Docs or DataSync on the left to get started.
2 changes: 1 addition & 1 deletion docs/datasync/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ If you're already tracking shipments with Terminal49, setup is a 3-step process

2. **1-hour configuration call**. Terminal49 makes sure you're getting data the way you want, configuring it to fit how you store all your current data.

3. **Start querying the data**. And then you're ready to go! Nothing new to learn — use the tools you already know, now with more data.
3. **Start querying the data**. And then you're ready to go! Nothing new to learn. Use the tools you already know, now with more data.

[Schedule a call with the Terminal49 Customer Success team](https://meetings.hubspot.com/kyle-blount) to get started.

Expand Down
Loading
Loading