# AGENTS Source: https://terminal49.com/docs/AGENTS # Documentation agent instructions These instructions guide automated changes for the Terminal49 docs in this repository. ## Scope * Primary docs live in `docs/` (MDX pages, `docs/docs.json`, and `docs/openapi.json`). * Do not edit generated files unless explicitly asked (e.g., `Terminal49-API.postman_collection.json`). ## Audience focus * Primary persona: integration engineers at BCOs/shippers/exporters who may not know logistics terms. * Secondary personas: logistics operators and decision-makers who know the domain but are less technical. * Each page should be laser-focused on one persona and one goal. ## Content goals by section * Getting Started: tutorial-style onboarding and first success within 30 minutes. * In Depth Guides: how-to and explanation content for workflows and best practices. * Useful Info: explanation/FAQ content that supports decisions and integrations. * API Reference: reference-only endpoint lookups, no narrative. ## Voice and terminology * Sound like a domain expert but stay friendly and easy to understand. * Use active voice and second person ("you"). * Use consistent product terms: "Terminal49", "tracking request", "shipment", "container", "webhook". * Define acronyms on first use (e.g., Bill of Lading (BOL)); link to a glossary if available. * Approved positioning phrases (use where relevant, do not invent new claims): * Automated Container Tracking API * Tracking shipments and containers from empty-out at the origin to empty-return at the destination * Single API to track bill of ladings, bookings, and container numbers with global coverage * Complete import milestones in North America including rail data ## API and code examples * Base URL is `https://api.terminal49.com/v2` unless a page says otherwise. * Examples should be realistic but safe (no real keys, emails, or customer data). * Use JSON with 2-space indentation; label code fences (e.g., `json, `bash, \`\`\`json http). * Prefer copy-pasteable snippets with complete headers. * For auth examples, use `Authorization: Token YOUR_API_KEY`. ## When updating API reference * If you change API behavior or schemas, update `docs/openapi.json` first. * Regenerate the Postman collection with: `openapi2postmanv2 -s docs/openapi.json -o Terminal49-API.postman_collection.json -p -O folderStrategy=Tags` ## MDX conventions * Every page must include frontmatter with a `title`. * Use Mintlify components like `` or `` sparingly for emphasis. * Keep headings concise and action-oriented. # Create container custom field Source: https://terminal49.com/docs/api-docs/api-reference/containers/create-container-custom-field post /containers/{container_id}/custom_fields Creates or updates a custom field on a container. If a custom field with the specified `api_slug` already exists, it will be updated. ## Path parameters | Parameter | Required | Description | | -------------- | -------- | ----------------------- | | `container_id` | Yes | The ID of the container | ## Request body | Parameter | Required | Description | | ---------- | -------- | ------------------------------------------------------------- | | `api_slug` | Yes | The slug of the custom field definition | | `value` | Yes | The value to set (type depends on the definition's data type) | ## Authorization Requires `update` permission on the container. ## Response Returns `201 Created` with the custom field resource on success. ## Behavior * Uses `find_or_initialize_by` internally, so it creates if missing or updates if it exists * Values are validated against the definition's data type * For enum fields, values are validated against the definition's options # Delete container custom field Source: https://terminal49.com/docs/api-docs/api-reference/containers/delete-container-custom-field delete /containers/{container_id}/custom_fields/{api_slug} Deletes a specific custom field from a container by its `api_slug`. ## Path parameters | Parameter | Required | Description | | -------------- | -------- | -------------------------------------------- | | `container_id` | Yes | The ID of the container | | `api_slug` | Yes | The api\_slug of the custom field definition | ## Authorization Requires `update` permission on the container. ## Response Returns `204 No Content` on success. # Edit a container Source: https://terminal49.com/docs/api-docs/api-reference/containers/edit-a-container patch /containers Update a container # Get a container Source: https://terminal49.com/docs/api-docs/api-reference/containers/get-a-container get /containers/{id} Retrieves the details of a container. # Get a container's raw events Source: https://terminal49.com/docs/api-docs/api-reference/containers/get-a-containers-raw-events get /containers/{id}/raw_events #### Deprecation warning The `raw_events` endpoint is provided as-is. For past events we recommend consuming `transport_events`. --- Get a list of past and future (estimated) milestones for a container as reported by the carrier. Some of the data is normalized even though the API is called raw_events. Normalized attributes: `event` and `timestamp` timestamp. Not all of the `event` values have been normalized. You can expect the the events related to container movements to be normalized but there are cases where events are not normalized. For past historical events we recommend consuming `transport_events`. Although there are fewer events here those events go through additional vetting and normalization to avoid false positives and get you correct data. # Get a container's transport events Source: https://terminal49.com/docs/api-docs/api-reference/containers/get-a-containers-transport-events get /containers/{id}/transport_events Get a list of past transport events (canonical) for a container. All data has been normalized across all carriers. These are a verified subset of the raw events may also be sent as Webhook Notifications to a webhook endpoint. This does not provide any estimated future events. See `container/:id/raw_events` endpoint for that. # Get container map GeoJSON Source: https://terminal49.com/docs/api-docs/api-reference/containers/get-container-map-geojson get /containers/{id}/map_geojson Returns a GeoJSON FeatureCollection containing all map-related data for a container, including port locations, current vessel position (if at sea), past vessel paths, and estimated future routes. The response can be directly used with most mapping libraries (Leaflet, Mapbox GL, Google Maps, etc.). This is a paid feature. Please contact sales@terminal49.com. This endpoint returns a GeoJSON FeatureCollection containing all map-related data for a container in a single response. The response includes port locations, current vessel position (if at sea), past vessel paths, and estimated future routes. For detailed documentation on the response structure, feature types, and their properties, see the [Container Map GeoJSON Data guide](/api-docs/in-depth-guides/routing). # List container custom fields Source: https://terminal49.com/docs/api-docs/api-reference/containers/list-container-custom-fields get /containers/{container_id}/custom_fields Lists all custom fields attached to a specific container. ## Path parameters | Parameter | Required | Description | | -------------- | -------- | ----------------------- | | `container_id` | Yes | The ID of the container | ## Authorization Requires `show` permission on the container. ## Response Returns a JSONAPI array of custom field resources including: * `value` - The raw stored value * `display_value` - Formatted value for display * Relationships to the definition and user who last updated the field # List containers Source: https://terminal49.com/docs/api-docs/api-reference/containers/list-containers get /containers Returns a list of container. The containers are returned sorted by creation date, with the most recently refreshed containers appearing first. This API will return all containers associated with the account. # Refresh container Source: https://terminal49.com/docs/api-docs/api-reference/containers/refresh-container patch /containers/{id}/refresh Schedules the container to be refreshed immediately from all relevant sources.

To be alerted of updates you should subscribe to the [relevant webhooks](/api-docs/in-depth-guides/webhooks). This endpoint is limited to 10 requests per minute.This is a paid feature. Please contact sales@terminal49.com. # Update container custom field Source: https://terminal49.com/docs/api-docs/api-reference/containers/update-container-custom-field patch /containers/{container_id}/custom_fields/{api_slug} Updates a specific custom field on a container by its `api_slug`. ## Path parameters | Parameter | Required | Description | | -------------- | -------- | -------------------------------------------- | | `container_id` | Yes | The ID of the container | | `api_slug` | Yes | The api\_slug of the custom field definition | ## Request body | Parameter | Required | Description | | --------- | -------- | -------------------- | | `value` | Yes | The new value to set | ## Authorization Requires `update` permission on the container. ## Response Returns `200 OK` with the updated custom field resource on success. # Create a custom field Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/create-a-custom-field post /custom_fields Use this endpoint to create a custom field value on a shipment or container. The field must reference an existing custom field definition. ## Request body | Parameter | Required | Description | | ---------- | -------- | ------------------------------------------------------- | | `entity` | Yes | Polymorphic relationship to a Shipment or Container | | `api_slug` | Yes | The slug of the custom field definition | | `value` | Yes | The field value (must match the definition's data type) | ## Value formats by data type | Data type | Expected value format | | ------------ | ---------------------------------------------------------------------------- | | `short_text` | Any string | | `number` | Numeric value | | `date` | Date string (parsed using definition's `default_format` or flexible parsing) | | `datetime` | DateTime string | | `boolean` | `true` or `false` | | `enum` | String matching one of the definition's option values | | `enum_multi` | Array of strings matching the definition's option values | ## Validation * Values are validated against the definition's data type * Enum values must match one of the definition's configured options * The `api_slug` must reference a definition belonging to your account or a Terminal49 template # Create a custom field definition Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/create-a-custom-field-definition post /custom_field_definitions Create a custom field definition to describe metadata you want to store on shipments or containers. ## Request body | Parameter | Required | Description | | ---------------- | -------- | ------------------------------------------------------------------- | | `entity_type` | Yes | The entity type this field applies to (`Shipment` or `Cargo`) | | `api_slug` | Yes | Unique identifier for the field | | `display_name` | Yes | Human-readable name for the field | | `data_type` | Yes | Data type for values (for example: `short_text`, `number`, `date`) | | `description` | No | Optional description of the field's purpose | | `validation` | No | Validation rules (for example: `required`, `pattern`, `max_length`) | | `default_format` | No | Default format string for numbers or dates | | `default_value` | No | Default value for new custom fields | | `reference_type` | No | Required when `data_type` is `reference` | # Create a custom field option Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/create-a-custom-field-option post /custom_field_definitions/{definition_id}/options Create a new option for an `enum` or `enum_multi` custom field definition. ## Path parameters | Parameter | Description | | --------------- | ---------------------------------------------------- | | `definition_id` | The unique identifier of the custom field definition | ## Request body | Parameter | Required | Description | | ---------- | -------- | ------------------------------------ | | `label` | Yes | Display label shown to users | | `value` | Yes | Stored value (unique per definition) | | `position` | No | Sort order for the option | ## Notes Options can only be added to definitions with `data_type` of `enum` or `enum_multi`. # Delete a custom field Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/delete-a-custom-field delete /custom_fields/{id} Use this endpoint to delete a custom field value from a shipment or container. ## Path parameters | Parameter | Description | | --------- | --------------------------------------------------------- | | `id` | The unique identifier of the custom field value to delete | ## Behavior * The custom field value is removed from the associated entity * Deleting a custom field value does not affect the underlying custom field definition # Delete a custom field definition Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/delete-a-custom-field-definition delete /custom_field_definitions/{id} Delete a custom field definition by its ID. ## Path parameters | Parameter | Description | | --------- | ---------------------------------------------------- | | `id` | The unique identifier of the custom field definition | ## Behavior Deleting a custom field definition also removes all associated custom field values. # Delete a custom field option Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/delete-a-custom-field-option delete /custom_field_definitions/{definition_id}/options/{option_id} Delete a custom field option by its ID. ## Path parameters | Parameter | Description | | --------------- | ---------------------------------------------------- | | `definition_id` | The unique identifier of the custom field definition | | `option_id` | The unique identifier of the option | ## Notes Deleting an option does not automatically update existing custom field values that reference it. # Get a custom field Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/get-a-custom-field get /custom_fields/{id} Use this endpoint to retrieve a single custom field value by its ID. ## Path parameters | Parameter | Description | | --------- | ----------------------------------------------- | | `id` | The unique identifier of the custom field value | ## Response The response includes: * `value` - The raw stored value (type depends on the field's data type) * `display_value` - Human-readable formatted value * Relationships to the associated entity (shipment or container), definition, and the user who last updated it ## Data types Custom fields support these data types, each with specific value handling: | Data type | Storage | Display format | | ------------ | --------------------------------- | -------------------------------------- | | `short_text` | String | As-is | | `number` | Decimal (precision: 18, scale: 6) | Formatted per `default_format` | | `date` | Date | `YYYY-MM-DD` or custom format | | `datetime` | DateTime | `YYYY-MM-DD HH:MM:SS` or custom format | | `boolean` | Boolean | `Yes` or `No` | | `enum` | String | Option label | | `enum_multi` | Comma-separated string | Comma-separated labels | # Get a custom field definition Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/get-a-custom-field-definition get /custom_field_definitions/{id} Use this endpoint to retrieve a single custom field definition by its ID. ## Path parameters | Parameter | Description | | --------- | ---------------------------------------------------- | | `id` | The unique identifier of the custom field definition | # Get a custom field option Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/get-a-custom-field-option get /custom_field_definitions/{definition_id}/options/{option_id} Retrieve a single custom field option by its ID. ## Path parameters | Parameter | Description | | --------------- | ---------------------------------------------------- | | `definition_id` | The unique identifier of the custom field definition | | `option_id` | The unique identifier of the option | # List custom field definitions Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/list-custom-field-definitions get /custom_field_definitions List all custom field definitions available to your account. ## Query filters | Filter | Description | | ---------------------- | --------------------------------------------- | | `filter[entity_type]` | Filter by entity type (`Shipment` or `Cargo`) | | `filter[data_type]` | Filter by data type | | `filter[display_name]` | Filter by display name (prefix match) | # List custom field options Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/list-custom-field-options get /custom_field_definitions/{definition_id}/options List all options for a custom field definition. ## Path parameters | Parameter | Description | | --------------- | ---------------------------------------------------- | | `definition_id` | The unique identifier of the custom field definition | # List custom fields Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/list-custom-fields get /custom_fields Use this endpoint to retrieve custom field values attached to your shipments and containers. Custom fields let you store additional metadata on entities to support your business workflows. ## Query filters Filter results using these query parameters: | Filter | Description | | ----------------------- | --------------------------------------------- | | `filter[entity_type]` | Filter by entity type (`Shipment` or `Cargo`) | | `filter[entity_id]` | Filter by the ID of the shipment or container | | `filter[definition_id]` | Filter by custom field definition ID | ## Response The response includes: * `value` - The raw stored value * `display_value` - Formatted value for display (e.g., formatted numbers, date strings, enum labels) * Relationships to the entity, definition, and user who last updated the field # Update a custom field Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/update-a-custom-field patch /custom_fields/{id} Use this endpoint to update an existing custom field value. ## Path parameters | Parameter | Description | | --------- | --------------------------------------------------------- | | `id` | The unique identifier of the custom field value to update | ## Request body | Parameter | Required | Description | | --------- | -------- | ----------------------------------------------------------- | | `value` | Yes | The new field value (must match the definition's data type) | ## Behavior * The new value is validated against the field definition's data type * For enum fields, the value must match one of the definition's configured options * The `updated_by` user is recorded for audit purposes * Update pathway tracking records the source of the change # Update a custom field definition Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/update-a-custom-field-definition patch /custom_field_definitions/{id} Update an existing custom field definition. ## Path parameters | Parameter | Description | | --------- | ---------------------------------------------------- | | `id` | The unique identifier of the custom field definition | ## Request body Provide the fields you want to update, such as `display_name`, `description`, `validation`, or `default_format`. ## Notes You cannot change `api_slug`, `entity_type`, or `data_type` after creation. # Update a custom field option Source: https://terminal49.com/docs/api-docs/api-reference/custom-fields/update-a-custom-field-option patch /custom_field_definitions/{definition_id}/options/{option_id} Update an existing custom field option. ## Path parameters | Parameter | Description | | --------------- | ---------------------------------------------------- | | `definition_id` | The unique identifier of the custom field definition | | `option_id` | The unique identifier of the option | ## Request body Provide the fields you want to update, such as `label` or `position`. # Document Representations Resource Source: https://terminal49.com/docs/api-docs/api-reference/document-representations/document-representations-resource Understand how document representation resources are returned through includes and webhook payloads. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. `document_representation` is a **resource type**, not a standalone endpoint. You receive it through: * document includes: `include=last_document_representation` * email submission nested includes: `include=documents.last_document_representation` * document webhook payloads (`document.extracted`, `document.extraction_failed`) in `included` ## Resource shape * `type`: `document_representation` * `attributes.schema_version`: public schema version string * `attributes.payload`: extracted key/value payload object * `attributes.created_at` * `attributes.updated_at` ## Where to fetch related schemas Use [`GET /document_schemas/{id}`](/api-docs/api-reference/document-schemas/get-a-document-schema) to retrieve schema metadata and payload contracts for document extraction outputs. # Get a document schema Source: https://terminal49.com/docs/api-docs/api-reference/document-schemas/get-a-document-schema get /document_schemas/{id} **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # delete-a-document Source: https://terminal49.com/docs/api-docs/api-reference/documents/delete-a-document delete /documents/{id} Soft-deletes (discards) the document. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Edit a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/edit-a-document patch /documents/{id} Updates manual extraction and classification fields. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Get a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/get-a-document get /documents/{id} **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Get a document download URL Source: https://terminal49.com/docs/api-docs/api-reference/documents/get-a-document-download-url get /documents/{id}/download_url Returns a presigned URL for downloading/viewing the current document file. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # List document types Source: https://terminal49.com/docs/api-docs/api-reference/documents/list-document-types get /documents/types Returns account-scoped allowed document types and labels. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # List documents Source: https://terminal49.com/docs/api-docs/api-reference/documents/list-documents get /documents Returns documents for the authenticated account. Supports filters, sorting, includes, and pagination. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Re-classify a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/re-classify-a-document post /documents/{id}/reclassify Triggers asynchronous classification for the document. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Re-extract a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/re-extract-a-document post /documents/{id}/reextract Triggers asynchronous extraction for the document. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Re-link a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/re-link-a-document post /documents/{id}/relink Re-runs reference linking for the document. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Rotate a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/rotate-a-document post /documents/{id}/rotate Queues a rotation update for image document types only. Non-image documents are not rotatable. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. After rotation is accepted, request [`GET /documents/{id}/download_url`](/api-docs/api-reference/documents/get-a-document-download-url) again to retrieve the updated image. # Upload a document Source: https://terminal49.com/docs/api-docs/api-reference/documents/upload-a-document post /documents Creates a document record. Provide an ActiveStorage signed blob id in `attached_document`. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. # Get an email submission Source: https://terminal49.com/docs/api-docs/api-reference/email-submissions/get-an-email-submission get /email_submissions/{id} # List email submissions Source: https://terminal49.com/docs/api-docs/api-reference/email-submissions/list-email-submissions get /email_submissions Returns email submissions for the authenticated account. # Get a metro area using the un/locode or the id Source: https://terminal49.com/docs/api-docs/api-reference/metro-areas/get-a-metro-area-using-the-unlocode-or-the-id get /metro_areas/{id} Return the details of a single metro area. # Create a party Source: https://terminal49.com/docs/api-docs/api-reference/parties/create-a-party post /parties Creates a new party # Edit a party Source: https://terminal49.com/docs/api-docs/api-reference/parties/edit-a-party patch /parties/{id} Updates a party # Get a party Source: https://terminal49.com/docs/api-docs/api-reference/parties/get-a-party get /parties/{id} Returns a party by it's given identifier # List parties Source: https://terminal49.com/docs/api-docs/api-reference/parties/list-parties get /parties Get a list of parties # Get a port using the locode or the id Source: https://terminal49.com/docs/api-docs/api-reference/ports/get-a-port-using-the-locode-or-the-id get /ports/{id} Return the details of a single port. # Create shipment custom field Source: https://terminal49.com/docs/api-docs/api-reference/shipments/create-shipment-custom-field post /shipments/{shipment_id}/custom_fields Creates or updates a custom field on a shipment. If a custom field with the specified `api_slug` already exists, it will be updated. ## Path parameters | Parameter | Required | Description | | ------------- | -------- | ---------------------- | | `shipment_id` | Yes | The ID of the shipment | ## Request body | Parameter | Required | Description | | ---------- | -------- | ------------------------------------------------------------- | | `api_slug` | Yes | The slug of the custom field definition | | `value` | Yes | The value to set (type depends on the definition's data type) | ## Authorization Requires `update` permission on the shipment. ## Response Returns `201 Created` with the custom field resource on success. ## Behavior * Uses `find_or_initialize_by` internally, so it creates if missing or updates if it exists * Values are validated against the definition's data type * For enum fields, values are validated against the definition's options # Delete shipment custom field Source: https://terminal49.com/docs/api-docs/api-reference/shipments/delete-shipment-custom-field delete /shipments/{shipment_id}/custom_fields/{api_slug} Deletes a specific custom field from a shipment by its `api_slug`. ## Path parameters | Parameter | Required | Description | | ------------- | -------- | -------------------------------------------- | | `shipment_id` | Yes | The ID of the shipment | | `api_slug` | Yes | The api\_slug of the custom field definition | ## Authorization Requires `update` permission on the shipment. ## Response Returns `204 No Content` on success. # Edit a shipment Source: https://terminal49.com/docs/api-docs/api-reference/shipments/edit-a-shipment patch /shipments/{id} Update a shipment # Get a shipment Source: https://terminal49.com/docs/api-docs/api-reference/shipments/get-a-shipment get /shipments/{id} Retrieves the details of an existing shipment. You need only supply the unique shipment `id` that was returned upon `tracking_request` creation. # List shipment custom fields Source: https://terminal49.com/docs/api-docs/api-reference/shipments/list-shipment-custom-fields get /shipments/{shipment_id}/custom_fields Lists all custom fields attached to a specific shipment. ## Path parameters | Parameter | Required | Description | | ------------- | -------- | ---------------------- | | `shipment_id` | Yes | The ID of the shipment | ## Authorization Requires `show` permission on the shipment. ## Response Returns a JSONAPI array of custom field resources including: * `value` - The raw stored value * `display_value` - Formatted value for display * Relationships to the definition and user who last updated the field # List shipments Source: https://terminal49.com/docs/api-docs/api-reference/shipments/list-shipments get /shipments Returns a list of your shipments. The shipments are returned sorted by creation date, with the most recent shipments appearing first. This api will return all shipments associated with the account. Shipments created via the `tracking_request` API aswell as the ones added via the dashboard will be retuned via this endpoint. # Resume tracking a shipment Source: https://terminal49.com/docs/api-docs/api-reference/shipments/resume-tracking-shipment patch /shipments/{id}/resume_tracking Resume tracking a shipment. Keep in mind that some information is only made available by our data sources at specific times, so a stopped and resumed shipment may have some information missing. # Stop tracking a shipment Source: https://terminal49.com/docs/api-docs/api-reference/shipments/stop-tracking-shipment patch /shipments/{id}/stop_tracking We'll stop tracking the shipment, which means that there will be no more updates. You can still access the shipment's previously-collected information via the API or dashboard. You can resume tracking a shipment by calling the `resume_tracking` endpoint, but keep in mind that some information is only made available by our data sources at specific times, so a stopped and resumed shipment may have some information missing. # Update shipment custom field Source: https://terminal49.com/docs/api-docs/api-reference/shipments/update-shipment-custom-field patch /shipments/{shipment_id}/custom_fields/{api_slug} Updates a specific custom field on a shipment by its `api_slug`. ## Path parameters | Parameter | Required | Description | | ------------- | -------- | -------------------------------------------- | | `shipment_id` | Yes | The ID of the shipment | | `api_slug` | Yes | The api\_slug of the custom field definition | ## Request body | Parameter | Required | Description | | --------- | -------- | -------------------- | | `value` | Yes | The new value to set | ## Authorization Requires `update` permission on the shipment. ## Response Returns `200 OK` with the updated custom field resource on success. # Get a single shipping line Source: https://terminal49.com/docs/api-docs/api-reference/shipping-lines/get-a-single-shipping-line get /shipping_lines/{id} Return the details of a single shipping line. # Shipping Lines Source: https://terminal49.com/docs/api-docs/api-reference/shipping-lines/shipping-lines get /shipping_lines Return a list of shipping lines supported by Terminal49. N.B. There is no pagination for this endpoint. # Get a terminal using the id Source: https://terminal49.com/docs/api-docs/api-reference/terminals/get-a-terminal-using-the-id get /terminals/{id} Return the details of a single terminal. # Infer Tracking Number (Beta) Source: https://terminal49.com/docs/api-docs/api-reference/tracking-requests/auto-detect-carrier post /tracking_requests/infer_number Predict the carrier SCAC (VOCC) and number type from a tracking number. Provide a container number, bill of lading number, or booking number and receive the predicted carrier with confidence and a decision value. Use this to auto-populate carrier fields before creating a tracking request. **Beta Feature** - This endpoint is currently in beta. The API is stable, but the schema and behavior may evolve based on feedback. ## What this endpoint does Give us a tracking number (container, bill of lading, or booking). We return: * The **predicted VOCC carrier SCAC** to use for tracking * The **predicted number type** * A confidence-driven **decision** (`auto_select`, `needs_confirmation`, `no_prediction`) We use machine learning prediction across container, bill of lading, and booking numbers. For container numbers, we leverage tens of millions of historical container movements to predict which carrier is moving the container (about 9 out of 10 times). ## How to use the result This endpoint is rate limited to 200 requests per minute per API key. Learn how to use Infer Tracking Number to reliably create tracking requests # Create a tracking request Source: https://terminal49.com/docs/api-docs/api-reference/tracking-requests/create-a-tracking-request post /tracking_requests To track an ocean shipment, you create a new tracking request. Two attributes are required to track a shipment. A `bill of lading/booking number` and a shipping line `SCAC`. Once a tracking request is created we will attempt to fetch the shipment details and it's related containers from the shipping line. If the attempt is successful we will create in new shipment object including any related container objects. We will send a `tracking_request.succeeded` webhook notification to your webhooks. If the attempt to fetch fails then we will send a `tracking_request.failed` webhook notification to your `webhooks`. A `tracking_request.succeeded` or `tracking_request.failed` webhook notificaiton will only be sent if you have atleast one active webhook.

This endpoint is limited to 100 tracking requests per minute. **Don't know the SCAC?** Call [Auto-Detect Carrier](/api-docs/api-reference/tracking-requests/auto-detect-carrier) first to identify the shipping line from your tracking number. # Edit a tracking request Source: https://terminal49.com/docs/api-docs/api-reference/tracking-requests/edit-a-tracking-request patch /tracking_requests/{id} Update a tracking request # Get a single tracking request Source: https://terminal49.com/docs/api-docs/api-reference/tracking-requests/get-a-single-tracking-request get /tracking_requests/{id} Get the details and status of an existing tracking request. # List tracking requests Source: https://terminal49.com/docs/api-docs/api-reference/tracking-requests/list-tracking-requests get /tracking_requests Returns a list of your tracking requests. The tracking requests are returned sorted by creation date, with the most recent tracking request appearing first. # Get a vessel using the id Source: https://terminal49.com/docs/api-docs/api-reference/vessels/get-a-vessel-using-the-id get /vessels/{id} Returns a vessel by id. `show_positions` is a paid feature. Please contact sales@terminal49.com. # Get a vessel using the imo Source: https://terminal49.com/docs/api-docs/api-reference/vessels/get-a-vessel-using-the-imo get /vessels/{imo} Returns a vessel by the given IMO number. `show_positions` is a paid feature. Please contact sales@terminal49.com. # Get vessel future positions Source: https://terminal49.com/docs/api-docs/api-reference/vessels/get-vessel-future-positions get /vessels/{id}/future_positions Returns the estimated route between two ports for a given vessel. The timestamp of the positions has fixed spacing of one minute. This is a paid feature. Please contact sales@terminal49.com. # Get vessel future positions from coordinates Source: https://terminal49.com/docs/api-docs/api-reference/vessels/get-vessel-future-positions-with-coordinates get /vessels/{id}/future_positions_with_coordinates Returns the estimated route between two ports for a given vessel from a set of coordinates. The timestamp of the positions has fixed spacing of one minute. This is a paid feature. Please contact sales@terminal49.com. # Get a single webhook notification Source: https://terminal49.com/docs/api-docs/api-reference/webhook-notifications/get-a-single-webhook-notification get /webhook_notifications/{id} # Get webhook notification payload examples Source: https://terminal49.com/docs/api-docs/api-reference/webhook-notifications/get-webhook-notification-payload-examples get /webhook_notifications/examples Returns an example payload as it would be sent to a webhook endpoint for the provided `event` # List webhook notifications Source: https://terminal49.com/docs/api-docs/api-reference/webhook-notifications/list-webhook-notifications get /webhook_notifications Return the list of webhook notifications. This can be useful for reconciling your data if your endpoint has been down. # Create a webhook Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/create-a-webhook post /webhooks You can configure a webhook via the API to be notified about events that happen in your Terminal49 account. These events can be realted to tracking_requests, shipments and containers. This is the recommended way tracking shipments and containers via the API. You should use this instead of polling our the API periodically. # Delete a webhook Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/delete-a-webhook delete /webhooks/{id} Delete a webhook # Edit a webhook Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/edit-a-webhook patch /webhooks/{id} Update a single webhook # Get single webhook Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/get-single-webhook get /webhooks/{id} Get the details of a single webhook # List webhook IPs Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/list-webhook-ips get /webhooks/ips Return the list of IPs used for sending webhook notifications. This can be useful for whitelisting the IPs on the firewall. # List webhooks Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/list-webhooks get /webhooks Get a list of all the webhooks # Trigger a webhook test delivery Source: https://terminal49.com/docs/api-docs/api-reference/webhooks/trigger-a-webhook post /webhooks/trigger Send a one-time test webhook notification payload to a target HTTPS URL without creating a webhook endpoint. # 3. List Your Shipments & Containers Source: https://terminal49.com/docs/api-docs/getting-started/list-shipments-and-containers ## Shipment and Container Data in Terminal49 After you've successfully made a tracking request, Terminal49 will begin to track shipments and store relevant information about that shipment on your behalf. The initial tracking request starts this process, collecting available data from Carriers and Terminals. Then, Terminal49 periodically checks for new updates adn pulls data from the carriers and terminals to keep the data we store up to date. You can access data about shipments and containers on your tracked shipments any time. We will introduce the basics of this method below. Keep in mind, however, that apart from initialization code, you would not usually access shipment data in this way. You would use Webhooks (described in the next section). A Webhook is another name for a web-based callback URL, or a HTTP Push API. They provide a method for an API to post a notification to your service. Specifically, a webhook is simply a URL that can receive HTTP Post Requests from the Terminal49 API. ## List all your Tracked Shipments If your tracking request was successful, you will now be able to list your tracked shipments. **Try it below. Click "Headers" and replace YOUR\_API\_KEY with your API key.** Sometimes it may take a while for the tracking request to show up, but usually no more than a few minutes. If you had trouble adding your first shipment, try adding a few more. **We suggest copy and pasting the response returned into a text editor so you can examine it while continuing the tutorial.** ```json http theme={null} { "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, which means that there are nifty libraries which can translate JSON into a fully fledged object model that can be used with an ORM. This is very powerful, but it also requires a larger, more structured payload to power the framework. The tradeoff, therefore, is that it's less convenient if you're parsing the JSON directly. Ultimately we strongly recommend you set yourself up with a good library to use JSON API to its fullest extent. But for the purposes of understanding the API's fundamentals and getting your feet wet, we'll work with the data directly. ## Authentication The API uses HTTP Bearer Token authentication. This means you send your API Key as your token in every request. Webhooks are associated with API tokens, and this is how the Terminal49 knows who to return relevant shipment information to. ## Anatomy of Shipments JSON Response Here's what you'll see come back after you get the /shipments endpoint. Note that for clarity I've deleted some of the data that is less useful right now, and replaced them with ellipses (...). Bolded areas are also mine to point out important data. The **Data** attribute contains an array of objects. Each object is of type "shipment" and includes attributes such as bill of lading number, the port of lading, and so forth. Each Shipment object also has Relationships to structured data objects, for example, Ports and Terminals, as well as a list of Containers which are on this shipment. You can write code to access these structured elements from the API. The advantage of this approach is that Terminal49 cleans and enhances the data that is provided from the steamship line, meaning that you can access a pre-defined object definition for a specific port in Los Angeles. ```jsx theme={null} { "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 Shipment into 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, we need to parse the JSON directly, making this example an ideal real world application of the API. ```jsx theme={null} 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](/api-docs/in-depth-guides/holds-and-fees). **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.** ```json http theme={null} { "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. ```jsx theme={null} // 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" } }, ... } }, ... ``` # 4. How to Receive Status Updates Source: https://terminal49.com/docs/api-docs/getting-started/receive-status-updates ## Using Webhooks to Receive Status Updates Terminal49 posts status updates to a webhook that you register with us. A Webhook is another name for a web-based callback URL, or a HTTP Push API. They provide a method for an API to post a notification to your service. Specifically, a webhook is simply a URL that can receive HTTP Post Requests from the Terminal49 API. The HTTP Post request from Terminal49 has a JSON payload which you can parse to extract the relevant information. ## How do I use a Webhook with Terminal49? First, you need to register a webhook. You can register as many webhooks as you like. Webhooks are associated with your account. All updates relating to that account are sent to the Webhook associated with it. You can setup a new webhook by visiting [https://app.terminal49.com/developers/webhooks](https://app.terminal49.com/developers/webhooks) and clicking the 'Create Webhook Endpoint' button. ![Webhook Editing Screen](https://raw.githubusercontent.com/Terminal49/t49-api-documentation/master/assets/images/new_webhook.png "Webhook Editing Screen") ## Authentication The API uses HTTP Bearer Token authentication. This means you send your API Key as your token in every request. Webhooks are associated with API tokens, and this is how the Terminal49 knows who to return relevant shipment information to. ## Anatomy of a Webhook Notification Here's what you'll see in a Webhook Notification, which arrives as a POST request to your designated URL. For more information, refer to the Webhook In Depth guide. Note that for clarity I've deleted some of the data that is less useful right now, and replaced them with ellipses (...). Bolded areas are also mine to point out important data. Note that there are two main sections: **Data.** The core information being returned. **Included**. Included are relevant objects that you are included for convenience. ```jsx theme={null} { "data": { "id": "87d4f5e3-df7b-4725-85a3-b80acc572e5d", "type": "webhook_notification", "attributes": { "id": "87d4f5e3-df7b-4725-85a3-b80acc572e5d", "event": "tracking_request.succeeded", "delivery_status": "pending", "created_at": "2020-09-13 14:46:37 UTC" }, "relationships": { ... } }, "included":[ { "id": "90873f19-f9e8-462d-b129-37e3d3b64c82", "type": "tracking_request", "attributes": { "request_number": "MEDUNXXXXXX", ... }, ... }, { "id": "66db1d2a-eaa1-4f22-ba8d-0c41b051c411", "type": "shipment", "attributes": { "created_at": "2020-09-13 14:46:36 UTC", "bill_of_lading_number": "MEDUNXXXXXX", "ref_numbers":[ null ], "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "port_of_lading_locode": "PLGDY", "port_of_lading_name": "Gdynia", .... }, "relationships": { ... }, "links": { "self": "/v2/shipments/66db1d2a-eaa1-4f22-ba8d-0c41b051c411" } }, { "id": "4d556105-015e-4c75-94a9-59cb8c272148", "type": "container", "attributes": { "number": "CRLUYYYYYY", "seal_number": null, "created_at": "2020-09-13 14:46:36 UTC", "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", ... }, "relationships": { .... } }, { "id": "129b695c-c52f-48a0-9949-e2821813690e", "type": "transport_event", "attributes": { "event": "container.transport.vessel_loaded", "created_at": "2020-09-13 14:46:36 UTC", "voyage_number": "032A", "timestamp": "2020-08-07 06:57:00 UTC", "location_locode": "PLGDY", "timezone": "Europe/Warsaw" }, ... } ] } ``` > ### Why so much JSON? (A note on JSON API) > > The Terminal49 API is JSON API compliant, which means that there are nifty libraries which can translate JSON into a fully fledged object model that can be used with an ORM. This is very powerful, but it also requires a larger, more structured payload to power the framework. The tradeoff, therefore, is that it's less convenient if you're parsing the JSON directly. Ultimately we strongly recommend you set yourself up with a good library to use JSON API to its fullest extent. But for the purposes of understanding the API's fundamentals and getting your feet wet, we'll work with the data directly. ### What type of webhook event is this? This is the first question you need to answer so your code can handle the webhook. The type of update can be found in \["data"]\["attributes"]. The most common Webhook notifications are status updates on tracking requests, like **tracking\_request.succeeded** and updates on ETAs, shipment milestone, and terminal availability. You can find what type of event you have received by looking at the "attributes", "event". ```jsx theme={null} "data" : { ... "attributes": { "id": "87d4f5e3-df7b-4725-85a3-b80acc572e5d", "event": "tracking_request.succeeded", "delivery_status": "pending", "created_at": "2020-09-13 14:46:37 UTC" }, } ``` ### Inclusions: Tracking Requests & Shipment Data When a tracking request has succeeded, the webhook event **includes** information about the shipment, the containers in the shipment, and the milestones for that container, so your app can present this information to your end users without making further queries to the API. In the payload below (again, truncated by ellipses for clarity) you'll see a list of JSON objects in the "included" section. Each object has a **type** and **attributes**. The type tells you what the object is. The attributes tell you the data that the object carries. Some objects have **relationships**. These are simply links to another object. The most essential objects in relationships are often included, but objects that don't change very often, for example an object that describes a teminal, are not included - once you query these, you should consider caching them locally. ```jsx theme={null} "included":[ { "id": "90873f19-f9e8-462d-b129-37e3d3b64c82", "type": "tracking_request", "attributes" : { ... } }, { "id": "66db1d2a-eaa1-4f22-ba8d-0c41b051c411", "type": "shipment", "attributes": { "created_at": "2020-09-13 14:46:36 UTC", "bill_of_lading_number": "MEDUNXXXXXX", "ref_numbers":[ null ], "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "port_of_lading_locode": "PLGDY", "port_of_lading_name": "Gdynia", .... }, "relationships": { ... }, "links": { "self": "/v2/shipments/66db1d2a-eaa1-4f22-ba8d-0c41b051c411" } }, { "id": "4d556105-015e-4c75-94a9-59cb8c272148", "type": "container", "attributes": { "number": "CRLUYYYYYY", "seal_number": null, "created_at": "2020-09-13 14:46:36 UTC", "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", ... }, "relationships": { .... } }, { "id": "129b695c-c52f-48a0-9949-e2821813690e", "type": "transport_event", "attributes": { "event": "container.transport.vessel_loaded", "created_at": "2020-09-13 14:46:36 UTC", "voyage_number": "032A", "timestamp": "2020-08-07 06:57:00 UTC", "location_locode": "PLGDY", "timezone": "Europe/Warsaw" }, ... } ] ``` ## Code Examples ### Registering a Webhook ```jsx theme={null} function registerWebhook(){ // Make a POST request with a JSON payload. options = { "method" : "POST" "headers" : { "content-type": "application/vnd.api+json", "authorization" : "Token YOUR_API_KEY" }, "payload" : { "data": { "type": "webhook", "attributes": { "url": "http://yourwebhookurl.com/webhook", "active": true, "events": ["tracking_request.succeeded"] } } } }; options.payload = JSON.stringify(data) var response = UrlFetchApp.fetch('https://api.terminal49.com/v2/webhooks', options); } ``` ### Receiving a Post Webhook Here's an example of some Javascript code that receives a Post request and parses out some of the desired data. ``` function receiveWebhook(postReq) { try { var json = postReq.postData.contents; var webhook_raw = JSON.parse(json); var webhook_data = webhook_raw["data"] var notif_string = ""; if (webhook_data["type"] == "webhook_notification"){ if (webhook_data["attributes"]["event"] == "shipment.estimated.arrival"){ /* the webhook "event" attribute tell us what event we are being notified * about. You will want to write a code path for each event type. */ var webhook_included = webhook_raw["included"]; // from the list of included objects, extract the information about the ETA update. This should be singleton. var etas = webhook_included.filter(isEstimatedEvent); // from the same list, extract the tracking Request information. This should be singleton. var trackingReqs = webhook_included.filter(isTrackingRequest); if(etas.length > 0 && trackingReqs.length > 0){ // therethis is an ETA updated for a specific tracking request. notif_string = "Estimated Event Update: " + etas[0]["attributes"]["event"] + " New Time: " + etas[0]["attributes"]["estimated_timestamp"]; notif_string += " for Tracking Request: " + trackingReqs[0]["attributes"]["request_number"] + " Status: " + trackingReqs[0]["attributes"]["status"]; } else { // this is a webhook type we haven't written handling code for. notif_string = "Error. Webhook Returned Unexpected Data."; } if (webhook_data["attributes"]["event"] == "shipment.estimated.arrival"){ } } return HtmlService.createHtmlOutput(notf_string); } catch (error){ return HtmlService.createHtmlOutput("Webhook failed: " + error); } } // JS helper functions to filter events of certain types. function isEstimatedEvent(item){ return item["type"] == "estimated_event"; } function isTrackingRequest(item){ return item["type"] == "tracking_request"; } ``` ## Try It Out & See More Sample Code Update your API key below, and register a simple Webhook. View the "Code Generation" button to see sample code. ```json http theme={null} { "method": "post", "url": "https://api.terminal49.com/v2/webhooks", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" }, "body": "{\r\n \"data\": {\r\n \"type\": \"webhook\",\r\n \"attributes\": {\r\n \"url\": \"https:\/\/webhook.site\/\",\r\n \"active\": true,\r\n \"events\": [\r\n \"tracking_request.succeeded\"\r\n ]\r\n }\r\n }\r\n}" } ``` # SDK Quickstart (TypeScript) Source: https://terminal49.com/docs/api-docs/getting-started/sdk-quickstart The SDK documentation has moved to the top-level SDK Docs section. * [Open the SDK quickstart](/sdk/quickstart) # 1. Start Here Source: https://terminal49.com/docs/api-docs/getting-started/start-here So you want to start tracking your ocean shipments and containers and you have a few BL numbers. Follow the guide. Our API responses use [JSONAPI](https://jsonapi.org/) schema. There are [client libraries](https://jsonapi.org/implementations/#client-libraries) available in almost every language. Our API should work with these libs out of the box. Our APIs can be used with any HTTP client; choose your favorite! We love Postman, it's a friendly graphical interface to a powerful cross-platform HTTP client. Best of all it has support for the OpenAPI specs that we publish with all our APIs. We have created a collection of requests for you to easily test the API endpoints with your API Key. Link to the collection below. **Run in Postman** *** ## Get an API Key Sign in to your Terminal49 account and go to your [developer portal](https://app.terminal49.com/developers/api-keys) page to get your API key. ### Authentication When passing your API key it should be prefixed with `Token`. For example, if your API Key is 'ABC123' then your Authorization header would look like: ``` "Authorization": "Token ABC123" ``` # 2. Tracking Shipments & Containers Source: https://terminal49.com/docs/api-docs/getting-started/tracking-shipments-and-containers Submitting a tracking request is how you tell Terminal49 to track a shipment for you. ## What is a Tracking Request? Your tracking request includes two pieces of data: * Your Bill of Lading, Booking number, or container number from the carrier. * The SCAC code for that carrier. **Don't know the SCAC?** Use the [Auto-Detect Carrier](/api-docs/in-depth-guides/auto-detect-carrier) endpoint to automatically identify the shipping line from your tracking number. You can see a complete list of supported SCACs in row 2 of the Carrier Data Matrix. ## What sort of numbers can I track? **Supported numbers** 1. Master Bill of Lading from the carrier (recommended) 2. Booking number from the carrier 3. Container number * Container number tracking support across ocean carriers is sometimes more limited. Please refer to the Carrier Data Matrix to see which SCACs are compatible with Container number tracking. **Unsupported numbers** * House Bill of Lading numbers (HBOL) * Customs entry numbers * Seal numbers * Internally generated numbers, for example PO numbers or customer reference numbers. ## How do I use Tracking Requests? Terminal49 is an event-based API, which means that the API can be used asynchronously. In general the data flow is: 1. You send a tracking request to the API with your Bill of Lading number and SCAC. 2. The API will respond that it has successfully received your Tracking Request and return the Shipment's data that is available at that time. 3. After you have submitted a tracking request, the shipment and all of the shipments containers are tracked automatically by Terminal49. 4. You will be updated when anything changes or more data becomes available. Terminal49 sends updates relating to your shipment via posts to the webhook you have registered. Generally speaking, updates occur when containers reach milestones. ETA updates can happen at any time. As the ship approaches port, you will begin to receive Terminal Availability data, Last Free day, and so forth. 5. At any time, you can directly request a list of shipments and containers from Terminal49, and the API will return current statuses and information. This is covered in a different guide. ## How do you send me the data relating to the tracking request? You have two options. First, you can poll for updates. This is the way we'll show you first. You can poll the `GET /tracking_request/{id}` endpoint to see the status of your request. You just need to track the ID of your tracking request, which is returned to you by the API. Second option is that you can register a webhook and the API will post updates when they happen. This is more efficient and therefore preferred. But it also requires some work to set up. A Webhook is another name for a web-based callback URL, or a HTTP Push API. Webhooks provide a method for an API to post a notification to your service. Specifically, a webhook is simply a URL that can receive HTTP Post Requests from the Terminal49 API. When we successfully lookup the Bill of Lading with the Carrier's SCAC, we will create a shipment, and send the event `tracking_request.succeeded` to your webhook endpoint with the associated record. If we encounter a problem we'll send the event `tracking_request.failed`. ## Authentication The API uses Bearer Token style authentication. This means you send your API Key as your token in every request. To get your API token to Terminal49 and go to your [account API settings](https://app.terminal49.com/settings/api) The token should be sent with each API request in the Authentication header: Support [dev@terminal49.com](dev@terminal49.com) ``` Authorization: Token YOUR_API_KEY ``` ## How to Create a Tracking Request Here is javascript code that demonstates sending a tracking request ```json theme={null} fetch("https://api.terminal49.com/v2/tracking_requests", { "method": "POST", "headers": { "content-type": "application/vnd.api+json", "authorization": "Token YOUR_API_KEY" }, "body": { "data": { "attributes": { "request_type": "bill_of_lading", "request_number": "", "scac": "" }, "type": "tracking_request" } } }) .then(response => { console.log(response); }) .catch(err => { console.error(err); }); ``` ## Anatomy of a Tracking Request Response Here's what you'll see in a Response to a tracking request. ```json theme={null} { "data": { "id": "478cd7c4-a603-4bdf-84d5-3341c37c43a3", "type": "tracking_request", "attributes": { "request_number": "xxxxxx", "request_type": "bill_of_lading", "scac": "MAEU", "ref_numbers": [], "created_at": "2020-09-17T16:13:30Z", "updated_at": "2020-09-17T17:13:30Z", "status": "pending", "failed_reason": null, "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": null } }, "links": { "self": "/v2/tracking_requests/478cd7c4-a603-4bdf-84d5-3341c37c43a3" } } } ``` Note that if you try to track the same shipment, you will receive an error like this: ```json theme={null} { "errors": [ { "status": "422", "source": { "pointer": "/data/attributes/request_number" }, "title": "Unprocessable Entity", "detail": "Request number 'xxxxxxx' with scac 'MAEU' already exists in a tracking_request with a pending or created status", "code": "duplicate" } ] } ``` **Why so much JSON? (A note on JSON API)** The Terminal49 API is JSON API compliant, which means that there are nifty libraries which can translate JSON into a fully fledged object model that can be used with an ORM. This is very powerful, but it also requires a larger, more structured payload to power the framework. The tradeoff, therefore, is that it's less convenient if you're parsing the JSON directly. Ultimately we strongly recommend you set yourself up with a good library to use JSON API to its fullest extent. But for the purposes of understanding the API's fundamentals and getting your feet wet, we'll work with the data directly. ## Try It: Make a Tracking Request Try it using the request maker below! 1. Enter your API token in the autorization header value. 2. Enter a value for the `request_number` and `scac`. The request number has to be a shipping line booking or master bill of lading number. The SCAC has to be a shipping line scac (see data sources to get a list of valid SCACs) Note that you can also access sample code in multiple languages by clicking the "Code Generation" below. **Tracking Request Troubleshooting** The most common issue people encounter is that they are entering the wrong number. Please check that you are entering the Bill of Lading number, booking number, or container number and not internal reference at your company or by your frieght forwarder. You can the number you are supplying by going to a carrier's website and using their tools to track your shipment using the request number. If this works, and if the SCAC is supported by T49, you should able to track it with us. If you're unsure of the correct SCAC, try the [Auto-Detect Carrier](/api-docs/api-reference/tracking-requests/auto-detect-carrier) endpoint first. It is entirely possible that's neither us nor you but the shipping line is giving us a headache. Temporary network problems, not populated manifest and other things happen! You can read on how are we handling them in the [Tracking Request Retrying](/api-docs/useful-info/tracking-request-retrying) section. Rate limiting: You can create up to 100 tracking requests per minute. You can always email us at [support@terminal49.com](mailto:support@terminal49.com) if you have persistent issues. ```json theme={null} { "method": "post", "url": "https://api.terminal49.com/v2/tracking_requests", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" }, "body": "{\r\n \"data\": {\r\n \"attributes\": {\r\n \"request_type\": \"bill_of_lading\",\r\n \"request_number\": \"\",\r\n \"scac\": \"\"\r\n },\r\n \"type\": \"tracking_request\"\r\n }\r\n}" } ``` ## Try It: List Your Active Tracking Requests We have not yet set up a webook to receive status updates from the Terminal49 API, so we will need to manually poll to check if the Tracking Request has succeeded or failed. **Try it below. Click "Headers" and replace `` with your API key.** ```json theme={null} { "method": "get", "url": "https://api.terminal49.com/v2/tracking_requests", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" } } ``` ## Next Up: Get your Shipments Now that you've made a tracking request, let's see how you can list your shipments and retrieve the relevant data. Go to this [page](https://help.terminal49.com/en/articles/8074102-how-to-initiate-shipment-tracking-on-terminal49) to see different ways of initiating shipment tracking on Terminal49. # How to add a Customer to a Tracking Request? Source: https://terminal49.com/docs/api-docs/in-depth-guides/adding-customer ## Why you would want to add a party to a tracking request? Adding a party to a tracking request allows you to associate customer information with the tracking request. The customer added to the tracking request will be assigned to the shipment when it is created, just like reference numbers and tags. This can help in organizing and managing your shipments more effectively. ## How to get the party ID? You can either find an existing party or create a new one. * To find an existing party, jump to [Listing all parties](#listing-all-parties) section. * To create a new party, jump to [Adding party for a customer](#adding-party-for-a-customer) section. ## Listing all parties You can list all parties associated with your account through the [API](/api-docs/api-reference/parties/list-parties). Endpoint: **GET** - [https://api.terminal49.com/v2/parties](/api-docs/api-reference/parties/list-parties) ```json Response theme={null} { "data": [ { "id": "PARTY_ID_1", "type": "party", "attributes": { "company_name": "COMPANY NAME 1", } }, { "id": "PARTY_ID_2", "type": "party", "attributes": { "company_name": "COMPANY NAME 2", } } ], "links": { "last": "", "next": "", "prev": "", "first": "", "self": "" }, "meta": { "size": 2, "total": 2 } } ``` After you get all the parties you would filter the parties by `company_name` to find the correct ID, either by looking through the list manually or using code to automate the process. ## How to add party to tracking request if you have the party ID? To add a customer to a tracking request, you need to add the party to the tracking request as a customer relationship while being created. **Note** that a party cannot be added to a tracking request that has already been created. Endpoint: **POST** - [https://api.terminal49.com/v2/tracking\_requests](/api-docs/api-reference/tracking-requests/create-a-tracking-request) ```json Request theme={null} { "data": { "type": "tracking_request", "attributes": { "request_type": "bill_of_lading", "request_number": "MEDUFR030802", "ref_numbers": [ "PO12345", "HBL12345", "CUSREF1234" ], "shipment_tags": [ "camembert" ], "scac": "MSCU" }, "relationships": { "customer": { "data": { "id": "PARTY_ID", "type": "party" } } } } } ``` After you send a **POST** request to create a tracking request, you will receive a response with the Tracking Request ID and customer relationship. You can use this tracking request ID to track the shipment. ```json Response theme={null} { "data": { "id": "TRACKING_REQUEST_ID", "type": "tracking_request", "attributes": { "request_type": "bill_of_lading", "request_number": "MEDUFR030802", "ref_numbers": [ "PO12345", "HBL12345", "CUSREF1234" ], "shipment_tags": [ "camembert" ], "scac": "MSCU" }, "relationships": { "tracked_object": { "data": null }, "customer": { "data": { "id": "PARTY_ID", "type": "party" } } }, "links": { "self": "/v2/tracking_requests/TRACKING_REQUEST_ID" } } } ``` ## Adding party for a customer For adding a customer to a tracking request, you need to create a party first. You can create a party through the [API](/api-docs/api-reference/parties/create-a-party). Endpoint: **POST** - [https://api.terminal49.com/v2/parties](/api-docs/api-reference/parties/create-a-party) ```json Request theme={null} { "data": { "type": "party", "attributes": { "company_name": "COMPANY NAME" } } } ``` After you send a **POST** request to create a party, you will receive a response with the Party ID. You can use this Party ID to add the customer to a tracking request. ```json Response theme={null} { "data": { "id": "PARTY_ID", "type": "party", "attributes": { "company_name": "COMPANY NAME" } } } ``` ## Editing a party You can update existing parties through the [API](/api-docs/api-reference/parties/edit-a-party). Endpoint: **PATCH** - [https://api.terminal49.com/v2/parties/PARTY\_ID](/api-docs/api-reference/parties/edit-a-party) ## Reading a party You can retrieve the details of an existing party through the [API](/api-docs/api-reference/parties/get-a-party). Endpoint: **GET** - [https://api.terminal49.com/v2/parties/PARTY\_ID](/api-docs/api-reference/parties/get-a-party) # Identify Your Carrier with the Infer API Source: https://terminal49.com/docs/api-docs/in-depth-guides/auto-detect-carrier Don't know the carrier SCAC for your tracking number? The Infer API identifies it automatically, helping you create successful tracking requests. **Beta Feature** β€” This guide covers the [Infer Number API](/api-docs/api-reference/tracking-requests/auto-detect-carrier), currently in beta. The API is stable for production use, but features may expand based on feedback. Every tracking request requires two things: **your tracking number** and **the shipping line's (carrier's) SCAC code**. But what if you don't know the SCAC? That's where the Infer API comes in. You've seen this feature in action β€” when you enter a number, we auto-suggest the carrier. Now this same intelligence is available via API. ## Why SCAC Matters To track a shipment or container, Terminal49 needs to know **which shipping line to ask** (also called the vessel-operating common carrier (VOCC)). The SCAC (Standard Carrier Alpha Code) we use here is the **shipping line SCAC for tracking** β€” i.e., the carrier operating the move we’re querying for events and shipment data. | You Have | You Need | The Challenge | | ------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | | Bill of Lading: `MAEU123456789` | Shipping line SCAC (VOCC SCAC) | Many MBOLs **do not include a prefix**, and even when they do, it may not reliably identify the shipping line you need for tracking. | | Container: `WHLU1234560` | Shipping line SCAC (VOCC SCAC) | The container owner code / leasing company is not always the carrier moving it, so the prefix alone is not enough. | | Booking: `987654321` | Shipping line SCAC (VOCC SCAC) | Booking formats vary widely and often contain no carrier identifier. | Without the correct **shipping line SCAC (VOCC SCAC)**, your tracking request can fail even if the number is valid. The Infer API predicts the shipping line SCAC + number type to increase the likelihood your tracking request succeeds. ## How the Infer API Helps Submit any tracking number, and the API returns: * **The predicted shipping line (SCAC)** β€” so you don't have to guess * **The number type** β€” container, bill of lading, or booking * **Validation results** β€” catches typos and invalid formats before you submit Just the number β€” no need to specify the shipping line or type Our system uses machine learning and historical data from millions of shipments to predict the shipping line. Use high-confidence results automatically, or prompt users to confirm With the right SCAC, your tracking request is far more likely to succeed ## Examples by Number Type 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. **Example Input:** `MSCU1234567` ```json Request theme={null} { "number": "MSCU1234567" } ``` ```json Response theme={null} { "data": { "attributes": { "number_type": "container", "validation": { "is_valid": true, "type": "container", "check_digit_passed": true }, "shipping_line": { "decision": "auto_select", "selected": { "scac": "MSCU", "name": "Mediterranean Shipping Company", "confidence": 1.0 }, "candidates": [ { "scac": "MSCU", "name": "Mediterranean Shipping Company", "confidence": 1.0 } ] } } } } ``` For container numbers, we use historical data to identify the shipping line with high accuracy (9/10 times). Always check the `decision` field to know if you should ask the user for confirmation. **What to do next:** ```bash theme={null} # Create tracking request with the detected SCAC POST /tracking_requests { "data": { "type": "tracking_request", "attributes": { "request_number": "MSCU1234567", "scac": "MSCU", "request_type": "container" } } } ``` Bill of lading numbers vary by carrier. Some contain prefixes, but others don't. The API uses machine learning to identify the carrier pattern. **Example Input:** `MAEU123456789` ```json Request theme={null} { "number": "MAEU123456789" } ``` ```json Response theme={null} { "data": { "attributes": { "number_type": "bill_of_lading", "validation": { "is_valid": true, "type": "shipment" }, "shipping_line": { "decision": "auto_select", "selected": { "scac": "MAEU", "name": "Maersk", "confidence": 0.98 }, "candidates": [ { "scac": "MAEU", "name": "Maersk", "confidence": 0.98 } ] } } } } ``` Maersk BLs typically start with `MAEU`, but other carriers may not have prefixes. The API analyzes the full format. **What to do next:** ```bash theme={null} # Create tracking request with the detected SCAC POST /tracking_requests { "data": { "type": "tracking_request", "attributes": { "request_number": "MAEU123456789", "scac": "MAEU", "request_type": "bill_of_lading" } } } ``` Booking numbers are the **hardest to identify** β€” they often don't contain carrier identifiers. **Example Input:** `987654321` ```json Request theme={null} { "number": "987654321" } ``` ```json Response theme={null} { "data": { "attributes": { "number_type": "booking", "validation": { "is_valid": null, "type": "shipment" }, "shipping_line": { "decision": "needs_confirmation", "selected": { "scac": "HLCU", "name": "Hapag-Lloyd", "confidence": 0.72 }, "candidates": [ { "scac": "HLCU", "name": "Hapag-Lloyd", "confidence": 0.72 }, { "scac": "ONE", "name": "Ocean Network Express", "confidence": 0.18 } ] } } } } ``` When `decision` is `needs_confirmation`, show the suggestion but **ask the user to verify**. Display the `candidates` list as options. **What to do next:** ```bash theme={null} # Show user the suggested carrier and candidates # After user confirms, create tracking request POST /tracking_requests { "data": { "type": "tracking_request", "attributes": { "request_number": "987654321", "scac": "HLCU", "request_type": "booking" } } } ``` ## Understanding the Response The `decision` field tells you how confident the prediction is and what action to take: | Decision | When it's used | What to do | | -------------------- | ---------------------------- | ----------------------------------------------------- | | `auto_select` | Confidence β‰₯ 95% | βœ… Safe to use automatically without user confirmation | | `needs_confirmation` | Confidence 70-95% | ⚠️ Show suggestion, ask user to confirm | | `no_prediction` | Confidence \< 70% or unknown | ❌ User must select carrier manually | For the best user experience, always handle all three decision types. Even when `no_prediction` is returned, you can still show the list of `candidates` as suggestions. The API validates numbers before returning predictions: | Field | Description | | -------------------- | ---------------------------------------------------------------- | | `is_valid` | `true` if format is valid, `false` if invalid, `null` if unknown | | `check_digit_passed` | For containers: ISO 6346 check digit verification | | `reason` | If invalid, explains why (e.g., "Invalid check digit") | Invalid numbers may still return a carrier prediction, but you should validate the format before creating a tracking request. | Field | Type | Description | | -------------------------- | ------ | ---------------------------------------------------------- | | `number_type` | string | Detected type: `container`, `bill_of_lading`, or `booking` | | `shipping_line.decision` | string | Confidence level for the prediction | | `shipping_line.selected` | object | Best match: `scac`, `name`, `confidence` | | `shipping_line.candidates` | array | All possible matches, ranked by confidence | See the [API Reference](/api-docs/api-reference/tracking-requests/auto-detect-carrier) for complete schema details. ## Integration Guide For developers implementing this API, here are code examples in different languages: ```javascript theme={null} async function getCarrierForNumber(trackingNumber, apiKey) { const response = await fetch( "https://api.terminal49.com/v2/tracking_requests/infer_number", { method: "POST", headers: { Authorization: `Token ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ number: trackingNumber }), } ); const { data } = await response.json(); const { decision, selected, candidates } = data.attributes.shipping_line; return { scac: selected?.scac, carrier: selected?.name, confidence: selected?.confidence, autoSelect: decision === "auto_select", needsConfirmation: decision === "needs_confirmation", candidates: candidates, }; } // Usage const result = await getCarrierForNumber("MSCU1234567", "YOUR_API_KEY"); if (result.autoSelect) { // Auto-fill carrier dropdown carrierDropdown.value = result.scac; } else if (result.needsConfirmation) { // Show suggestion with confirmation prompt showCarrierSuggestion(result.carrier, result.candidates); } ``` ```python theme={null} import requests def get_carrier_for_number(tracking_number: str, api_key: str) -> dict: """Get carrier prediction for a tracking number.""" response = requests.post( 'https://api.terminal49.com/v2/tracking_requests/infer_number', headers={ 'Authorization': f'Token {api_key}', 'Content-Type': 'application/json' }, json={'number': tracking_number} ) result = response.json() shipping_line = result['data']['attributes']['shipping_line'] return { 'scac': shipping_line['selected']['scac'] if shipping_line.get('selected') else None, 'carrier': shipping_line['selected']['name'] if shipping_line.get('selected') else None, 'confidence': shipping_line['selected']['confidence'] if shipping_line.get('selected') else None, 'auto_select': shipping_line['decision'] == 'auto_select', 'needs_confirmation': shipping_line['decision'] == 'needs_confirmation', 'candidates': shipping_line.get('candidates', []) } # Usage result = get_carrier_for_number("MSCU1234567", "YOUR_API_KEY") if result['auto_select']: # Auto-fill carrier dropdown carrier_dropdown.value = result['scac'] elif result['needs_confirmation']: # Show suggestion with confirmation prompt show_carrier_suggestion(result['carrier'], result['candidates']) ``` ```bash theme={null} curl -X POST https://api.terminal49.com/v2/tracking_requests/infer_number \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"number": "MSCU1234567"}' ``` ## Rate Limits | Setting | Value | | ------------------- | ----------------------- | | Requests per minute | 200 | | Rate limit header | `Retry-After` (seconds) | Rate limit errors return HTTP 429 with a `Retry-After` header. Respect this header to avoid extended throttling. ## What's Next? Full API specification with request/response schemas and try it in the playground Use the detected SCAC to start tracking your shipment See which carriers we support and their data availability Learn what happens after you submit a tracking request # Container Statuses Source: https://terminal49.com/docs/api-docs/in-depth-guides/container-statuses The `current_status` attribute on container objects provides a high-level view of where a container is in its journey. This guide explains the different status values and their meanings. ## Available Status Values The `current_status` field can have one of the following values: ### new **Default state** - The container is tracked but we don't yet have enough information to determine its actual status. This is the initial state when tracking begins. ### on\_ship **In transit by vessel** - The container is on a ship at any point prior to arrival at the Port of Discharge (POD). This status can apply at multiple stages: * During the ocean voyage from origin to destination * Before vessel departure from the Port of Lading * Any time the container is loaded on a vessel ### available **Ready for pickup** - The container has arrived at the POD or inland destination and is confirmed available for pickup. You can proceed with arranging pickup when you see this status. For a definitive readiness check that combines `available_for_pickup` with hold data, see [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees). ### not\_available **Arrived but not ready** - The container is at the POD or inland destination but is not yet available for pickup. This could be due to: * Customs holds * Terminal holds * Documentation requirements * Other restrictions See [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees) for details on specific hold types and how to determine when the container is released. ### grounded **Availability unknown** - The container is physically at the POD, but we don't currently know whether it's available for pickup or not. This typically means the terminal isn't providing real-time availability data. ### awaiting\_inland\_transfer **Moving inland** - The container is either: * Still at the POD waiting to be loaded onto rail for an inland move * In transit between the POD and a rail terminal * At a rail terminal but not yet loaded onto a rail car This status is specific to shipments with inland rail movements. ### on\_rail **In transit by rail** - The container has been loaded onto a rail car and is being transported to its inland destination. ### picked\_up **Out for delivery** - The container has been picked up from the terminal or facility for delivery. ### off\_dock **At alternative facility** - The container has been moved to a different terminal or off-dock storage facility for pickup. You may need to go to this alternative location rather than the original POD terminal. ### delivered **Delivery confirmed** - This status is only shown when delivery has been [manually marked as delivered](https://help.terminal49.com/articles/4713318249-how-to-mark-containers-as-delivered) through the Terminal49 dashboard. ### empty\_returned **Container returned empty** - The container has been emptied and returned to the shipping line or designated return location. ### dropped **Not currently used** - This status value is defined but not actively used in the system. ### loaded **Not currently used** - This status value is defined but not actively used in the system. ## Important Considerations ### Status Accuracy The logic to derive container statuses is complex and involves processing data from multiple sources including: * Shipping line updates * Terminal systems * Rail carrier feeds * Manual updates **There can sometimes be errors in the reported `current_status`**. When making critical business decisions, we recommend: * Cross-referencing with transport events * Contacting the terminal directly for time-sensitive pickups ### Status Transitions Containers don't always follow a linear path through these statuses. For example: * A container may go from `on_ship` directly to `available` if terminal data arrives quickly * A container might alternate between `available` and `not_available` if holds are placed and removed * The status may remain as `new` for some time if data from the shipping line is delayed ### API Usage To get the current status of a container, you can read the container's `current_status` attribute in your API responses: ```bash theme={null} GET /v2/containers/{id} ``` The response will include: ```json theme={null} { "data": { "id": "ff77a822-23a7-4ccd-95ca-g534c071baaf3", "type": "container", "attributes": { "number": "KOCU4959010", "current_status": "available", ... } } } ``` # Direct Upload for Documents Source: https://terminal49.com/docs/api-docs/in-depth-guides/direct-upload-documents Upload files with the direct upload flow, then create Terminal49 documents with the returned signed_id. Use this guide when your app needs to upload a file first and then create a Terminal49 document. Any client stack can use this flow as long as it can make standard HTTP requests. ## Overview 1. Request a direct upload blob payload from Terminal49. 2. Upload the file bytes to the returned `direct_upload.url` using the returned headers. 3. Store the returned `signed_id`. 4. Create a Terminal49 document with `attached_document = signed_id`. ## 1) Request a direct upload blob Endpoint: `POST /rails/active_storage/direct_uploads` Send metadata for the file you want to upload: ```json theme={null} { "blob": { "filename": "1462486 order.pdf", "content_type": "application/pdf", "byte_size": 35672, "checksum": "tZTfawHSrI1hiuOZQ0cQRg==" } } ``` ### Blob attributes explained | Attribute | Type | What it is | How to create it | | -------------- | ------- | ------------------------------------------------ | --------------------------------------------------------------------------- | | `filename` | string | Original file name users see. | Use the file name from the uploaded file (for example `1462486 order.pdf`). | | `content_type` | string | MIME type of the file. | Detect from file extension or file bytes (for PDF use `application/pdf`). | | `byte_size` | integer | Exact file size in bytes. | Read the file size from your filesystem or uploaded file object. | | `checksum` | string | Base64-encoded MD5 digest of the raw file bytes. | Compute MD5 on file bytes, then Base64-encode the binary MD5 result. | ### Example ways to generate values Get file size in bytes: ```bash theme={null} wc -c < "1462486 order.pdf" ``` Compute checksum (`Base64(MD5(file_bytes))`): ```bash theme={null} openssl md5 -binary "1462486 order.pdf" | openssl base64 ``` `checksum` must match the exact bytes you upload in step 2, or the upload will fail. Example response: ```json theme={null} { "id": "96b6d878-0341-4ce3-8b3c-06767f6f08eb", "key": "883c4cf4-b086-4698-a620-5ffa16cc95ef/pqjug51un0gobs6x72ez0q9e4so4", "filename": "1462486 order.pdf", "content_type": "application/pdf", "metadata": {}, "service_name": "amazon", "byte_size": 35672, "checksum": "tZTfawHSrI1hiuOZQ0cQRg==", "created_at": "2026-03-26T18:49:37Z", "signed_id": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWs1Tm1JMlpEZzNPQzB3TXpReExUUmpaVE10T0dJell5MHdOamMyTjJZMlpqQTRaV0lHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--f5605d2c1e90ce3b54ef1a193f84530f954184a5", "direct_upload": { "url": "https://...s3.amazonaws.com/...signature...", "headers": { "Content-Type": "application/pdf", "Content-MD5": "tZTfawHSrI1hiuOZQ0cQRg==", "Content-Disposition": "inline; filename=\"1462486 order.pdf\"; filename*=UTF-8''1462486%20order.pdf" } } } ``` ## 2) Upload the file bytes to `direct_upload.url` Use `direct_upload.url` to send the file, and send the `direct_upload.headers` object as request headers. Use whatever response is returned by that upload request. ```bash theme={null} curl -X PUT "$DIRECT_UPLOAD_URL" \ -H "Content-Length: 35672" \ -H "Content-Type: application/pdf" \ -H "Content-MD5: tZTfawHSrI1hiuOZQ0cQRg==" \ -H "Content-Disposition: inline; filename=\"1462486 order.pdf\"; filename*=UTF-8''1462486%20order.pdf" \ --data-binary @"/path/to/1462486 order.pdf" ``` ## 3) Persist `signed_id` in your app Save the `signed_id` with your internal record. You will use this value in the next step. Do not send the S3 URL to `POST /documents`. Send `signed_id` in `attached_document`. ## 4) Create the document using `attached_document` ```json theme={null} { "data": { "type": "document", "attributes": { "name": "1462486 order.pdf", "attached_document": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWs1Tm1JMlpEZzNPQzB3TXpReExUUmpaVE10T0dJell5MHdOamMyTjJZMlpqQTRaV0lHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--f5605d2c1e90ce3b54ef1a193f84530f954184a5" } } } ``` Endpoint: [`POST /documents`](/api-docs/api-reference/documents/upload-a-document) # Document Processing Workflows Source: https://terminal49.com/docs/api-docs/in-depth-guides/document-processing-workflows Submit documents by email or API, then consume extraction results via webhooks. This guide is for first-time integrators building document automation. You can submit documents in two ways: * Email attachments to your unique account docs alias * API endpoint Both follow the same customer-facing lifecycle: submit -> classify -> extract -> webhook result. ## Workflow Diagrams ```mermaid theme={null} flowchart LR A[User emails document attachments] --> B[Upload File] --> C[API /POST Documents] C --> D[Terminal49 receives and parses documents] D --> E[Terminal49 classifies documents] E --> F[Terminal49 extracts structured data] F --> G[Terminal49 sends webhook result] ``` ## Workflow: Step-by-Step Use email (attachments to your docs alias) or Upload directly by API Terminal49 classifies and extracts data asynchronously. You receive `document.extracted` or `document.extraction_failed`. If the same file content already exists for your account, it is treated as duplicate and not processed again. POST document through endpoint. Used by emailΒ  Treat submission as asynchronous. Do not assume extraction is complete immediately after upload/email. ## Technical Implementation (One End-to-End Example) Example scenario: user uploads one file, `invoice.pdf`. ### 1) Submit the document `POST /documents` Before creating the document, complete the direct upload flow and get a `signed_id`: [`Direct Upload for Documents`](/api-docs/in-depth-guides/direct-upload-documents). Note: `attached_document` is the S3 `signed_id` from the file direct upload. ```json theme={null} { "data": { "type": "document", "attributes": { "name": "invoice.pdf", "attached_document": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBLi4u" } } } ``` Response (`201`): ```json theme={null} { "data": { "id": "5ab53a5e-0d68-4a8f-8d3d-1d24555d20cb", "type": "document", "attributes": { "name": "invoice.pdf", "document_type": null, "file_name": "invoice.pdf", "file_content_type": "application/pdf", "file_size_bytes": 248193, "created_at": "2026-03-26T08:14:24Z", "updated_at": "2026-03-26T08:14:24Z" } } } ``` ### 2) Receive extraction webhook `document.extracted` example: ```json theme={null} { "data": { "id": "40cb28de-63ee-4542-909e-a19efe46904d", "type": "webhook_notification", "attributes": { "event": "document.extracted", "delivery_status": "pending", "created_at": "2026-03-26T08:17:06Z", "version": "2026-03-10" }, "relationships": { "document": { "data": { "id": "5ab53a5e-0d68-4a8f-8d3d-1d24555d20cb", "type": "document" } } } }, "included": [ { "id": "5ab53a5e-0d68-4a8f-8d3d-1d24555d20cb", "type": "document", "attributes": { "name": "invoice.pdf", "document_type": "commercial_invoice", "source": "upload", "file_name": "invoice.pdf", "file_content_type": "application/pdf", "file_size_bytes": 248193, "created_at": "2026-03-26T08:14:24Z", "updated_at": "2026-03-26T08:17:05Z" }, "relationships": { "account": { "data": { "id": "91d5b7cc-6d3f-4c87-b8bb-f5f31ed866f4", "type": "account" } }, "user": { "data": { "id": "fa25bdf2-0692-48f9-a8a7-cad8eb99527f", "type": "user" } }, "email_submission": { "data": { "id": "7de2c356-5d2a-4d6e-99f4-6f0d2d63e357", "type": "email_submission" } }, "last_document_representation": { "data": { "id": "ab1fba20-6b7b-4d5f-95e8-e2c55a7a8f89", "type": "document_representation" } } }, "links": { "self": "/documents/5ab53a5e-0d68-4a8f-8d3d-1d24555d20cb", "download": "/documents/5ab53a5e-0d68-4a8f-8d3d-1d24555d20cb/download_url" } }, { "id": "7de2c356-5d2a-4d6e-99f4-6f0d2d63e357", "type": "email_submission", "attributes": { "subject": "Invoice #INV-10027", "body_preview": "Please find attached invoice INV-10027.", "from": [ "ap@acme-manufacturing.com" ], "to": [ "docs+account@terminal49.com" ], "cc": [], "message_id": "", "sent_at": "2026-03-26T08:14:11Z", "created_at": "2026-03-26T08:14:12Z", "updated_at": "2026-03-26T08:14:12Z" } }, { "id": "ab1fba20-6b7b-4d5f-95e8-e2c55a7a8f89", "type": "document_representation", "attributes": { "schema_version": "2026-03-23", "payload": { "invoice_number": "INV-10027", "invoice_date": "2026-03-25", "supplier_name": "Acme Manufacturing Ltd", "total_amount": "12450.00", "currency": "USD" }, "created_at": "2026-03-26T08:17:05Z", "updated_at": "2026-03-26T08:17:05Z" } } ] } ``` ### 3) Persist extracted outcome in your system Use the webhook `event` and included `document` payload to update your internal record for that document. ## Webhooks You Should Handle | Event | Meaning | | ---------------------------- | --------------------------------- | | `document.extracted` | Extraction completed successfully | | `document.extraction_failed` | Extraction did not complete | ## Use these endpoints while integrating * [`GET /webhook_notifications/examples`](/api-docs/api-reference/webhook-notifications/get-webhook-notification-payload-examples) * [`POST /webhooks/trigger`](/api-docs/api-reference/webhooks/trigger-a-webhook) Webhook event availability depends on your account configuration. If you are not receiving expected events, contact Terminal49 support. ## APIs Involved * [`POST /documents`](/api-docs/api-reference/documents/upload-a-document) * [`GET /documents`](/api-docs/api-reference/documents/list-documents) * [`GET /documents/{id}`](/api-docs/api-reference/documents/get-a-document) * [`GET /documents/{id}/download_url`](/api-docs/api-reference/documents/get-a-document-download-url) * [`GET /email_submissions`](/api-docs/api-reference/email-submissions/list-email-submissions) * [`GET /email_submissions/{id}`](/api-docs/api-reference/email-submissions/get-an-email-submission) * [`GET /document_schemas/{id}`](/api-docs/api-reference/document-schemas/get-a-document-schema) * [`Document representations resource`](/api-docs/api-reference/document-representations/document-representations-resource) ## Planned (Not Live Yet) * `email_submission.created` webhook event after inbound email acceptance. # Event Timestamps Source: https://terminal49.com/docs/api-docs/in-depth-guides/event-timestamps Through the typical container lifecycle events occur across multiple timezones. Wheverever you see a timestamp for some kind of transporation event, there should be a corresponding [IANA tz](https://www.iana.org/time-zones). Event timestamps are stored and returned in UTC. If you wish to present them in the local time you need to convert that UTC timestamp using the corresponding timezone. ### Example If you receive a container model with the attributes ``` 'pod_arrived_at': '2022-12-22T07:00:00Z', 'pod_timezone': 'America/Los_Angeles', ``` then the local time of the `pod_arrived_at` timestamp would be `2022-12-21T23:00:00 PST -08:00` ## When the corresponding timezone is null When there is event that occurs where Terminal49 cannot determine the location (and therefore the timezone) of the event the system is unable to store the event in true UTC. In this scenario we take timestamp as given from the source and parse it in UTC. ### Example ``` 'pod_arrived_at': '2022-12-22T07:00:00Z', 'pod_timezone': null, ``` then the local time of the `pod_arrived_at` timestamp would be `2022-12-22T07:00:00` and the timezone is unknown. (Assuming the source was returning localized timestamps) ## System Timestamps Timestamps representing changes within the Terminal49 system (e.g. `created_at`, `updated_at`, `terminal_checked_at`) are stored and represented in UTC and do not have a TimeZone. # Container Holds, Fees, and Release Readiness Source: https://terminal49.com/docs/api-docs/in-depth-guides/holds-and-fees Determine when an import container is released for pickup by reading holds, fees, and availability data. After a container is discharged at the Port of Discharge (POD), the terminal and government agencies may place holds or assess fees before the container can be picked up. For shipments with inland rail moves, holds and fees can also apply at the inland destination. Your integration needs to monitor these fields to determine when a container is actually released and ready for pickup. Terminal49 normalizes hold and fee data across 150+ terminal sources into two structured arrays on the container object: `holds_at_pod_terminal` and `fees_at_pod_terminal`. This guide shows you how to use them. The field names reference `pod_terminal` for historical reasons, but these fields report hold and fee data regardless of whether the container is at a port terminal or an inland rail destination. The same readiness logic applies in both scenarios. ## Determine if a container is ready for pickup The most common question is straightforward: **can I pick up this container?** You need two fields from the container's `attributes` to answer it: * `available_for_pickup` β€” a boolean the terminal sets when the container is cleared for release * `holds_at_pod_terminal` β€” an array of active holds blocking pickup Use them together. A container is ready for pickup when `available_for_pickup` is `true` **and** there are no active holds: ```javascript theme={null} function isReadyForPickup(container) { const { available_for_pickup, holds_at_pod_terminal } = container.attributes; const hasActiveHolds = holds_at_pod_terminal.some(h => h.status === 'hold'); return available_for_pickup === true && !hasActiveHolds; } ``` Here is the full decision logic: ```mermaid theme={null} flowchart TD Start["Container discharged at POD"] --> CheckAvailable{"available_for_pickup\n== true?"} CheckAvailable -->|Yes| VerifyHolds{"holds array\nempty?"} CheckAvailable -->|No| CheckHolds{"Any active\nholds?"} VerifyHolds -->|Yes| Ready["Ready for pickup"] VerifyHolds -->|No| OutOfSync["Data may be out of sync\nWait for next update"] CheckHolds -->|Yes| Blocked["Blocked β€” resolve\nthe active holds"] CheckHolds -->|No| NotYet["Not yet released\nMonitor for updates"] ``` Treat `available_for_pickup: true` with an empty holds array as the definitive signal that the container is ready. When holds and `available_for_pickup` disagree β€” for example, holds are cleared but `available_for_pickup` is still `false` β€” wait for the next `container.updated` webhook or poll the container again. Terminal data is sourced from multiple systems on varying schedules, so brief inconsistencies can occur. ## Where to find holds and fees Both fields live on the container's `attributes` object in the V2 API: * `holds_at_pod_terminal` β€” active holds blocking or flagging pickup * `fees_at_pod_terminal` β€” fees assessed at the terminal [`GET /v2/containers/{id}`](/api-docs/api-reference/containers/get-a-container) ```json theme={null} { "data": { "id": "3cd51f0e-eb18-4399-9f90-4c8a22250f63", "type": "container", "attributes": { "number": "COSU1186800", "available_for_pickup": false, "holds_at_pod_terminal": [ { "name": "customs", "status": "hold", "description": "CBP HOLD" } ], "fees_at_pod_terminal": [ { "type": "demurrage", "amount": 850.00, "currency_code": "USD" } ] } } } ``` An empty array (`[]`) means there are no active holds or fees of that type. ## Hold types at a glance Each item in `holds_at_pod_terminal` is a `terminal_hold` object: | Field | Type | Description | | ------------- | -------------- | ----------------------------------------- | | `name` | string | The canonical hold type (see table below) | | `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. | Hold name | Description | Who resolves it | | --------- | ------------------------------------ | -------------------------------------- | | `freight` | Carrier freight charges unpaid | Shipping line or freight forwarder | | `customs` | CBP hold β€” docs, exam, or inspection | Licensed customs broker | | `USDA` | USDA phytosanitary inspection | Customs broker or USDA compliance team | | `VACIS` | Non-intrusive X-ray / gamma-ray scan | Customs broker | | `TMF` | Terminal management fee (pier pass) | Pay terminal directly | | `other` | Unmapped hold β€” check `description` | Terminal or broker | Hold names are case-sensitive. `USDA`, `VACIS`, and `TMF` are uppercase. `freight`, `customs`, and `other` are lowercase. Match values exactly in your code. The ocean carrier has placed a freight hold because the freight charges have not been paid or confirmed. The container will not be released until the carrier lifts this hold. ```json theme={null} { "name": "freight", "status": "hold", "description": null } ``` **Who resolves it:** Contact the shipping line or your freight forwarder to confirm payment status. US Customs and Border Protection (CBP) has placed a hold. This can occur due to documentation issues, a random examination, or a targeted inspection. The container cannot be released until CBP clears it. ```json theme={null} { "name": "customs", "status": "hold", "description": "CBP HOLD" } ``` **Who resolves it:** Your licensed customs broker. Resolution time varies from hours to several days depending on the examination type. The US Department of Agriculture (USDA) has flagged the shipment for a phytosanitary inspection. Common for shipments containing food, plants, wood packaging, or agricultural products. ```json theme={null} { "name": "USDA", "status": "hold", "description": null } ``` **Who resolves it:** Your customs broker or USDA compliance team. Inspections typically happen at the terminal or a USDA-approved facility. The container has been flagged for a VACIS (Vehicle and Cargo Inspection System) scan β€” a non-intrusive gamma-ray or X-ray inspection conducted by CBP. You may also see this referred to as an NII (Non-Intrusive Inspection) exam. ```json theme={null} { "name": "VACIS", "status": "hold", "description": "VACIS EXAM" } ``` **Who resolves it:** Your customs broker. The exam fee (if assessed) will appear separately in `fees_at_pod_terminal` as type `"exam"`. A Terminal Management Fee (TMF) hold is placed by the terminal itself β€” sometimes called a pier pass or terminal gate fee. This hold is typically resolved by paying the fee directly to the terminal. ```json theme={null} { "name": "TMF", "status": "hold", "description": null } ``` **Who resolves it:** Pay the terminal fee. Your drayage carrier or port agent can assist. A hold that Terminal49 could not map to a specific type. The raw terminal text, when available, appears in the `description` field. ```json theme={null} { "name": "other", "status": "hold", "description": "TERMINAL HOLD - SEE CUSTOMER SERVICE" } ``` **What to do:** Use the `description` to identify the specific issue and contact the terminal or your broker for resolution. A `status` of `"pending"` means the terminal has flagged a hold as expected but not yet active. Treat it as a warning that a hold is likely incoming. When the hold becomes active, the status changes to `"hold"` and you receive a `container.updated` webhook notification. ## Fee types at a glance Each item in `fees_at_pod_terminal` is a `terminal_fee` object: | Field | Type | Description | | --------------- | ------ | ----------------------------------------- | | `type` | string | The canonical fee type (see table below) | | `amount` | number | Fee amount in local currency | | `currency_code` | string | ISO 4217 currency code, typically `"USD"` | | Fee type | Description | Charged by | | --------------------- | -------------------------------------------------------- | ------------------------- | | `demurrage` | Daily charge after carrier free time expires | Ocean carrier | | `extended_dwell_time` | Terminal charge for prolonged dwell | Terminal | | `exam` | CBP/USDA inspection cost | Terminal or exam facility | | `total` | Combined total of all fees (may overlap with line items) | See individual items | | `other` | Unmapped fee type | Varies | A daily charge assessed by the **ocean carrier** when the container is not picked up within the free time period. Demurrage starts accruing after the carrier's free time expires and increases every day. ```json theme={null} { "type": "demurrage", "amount": 1250.00, "currency_code": "USD" } ``` **Note:** Demurrage is charged by the carrier, not the terminal. The terminal reports it, but you pay the carrier. An Extended Dwell Time (EDT) fee charged by the **terminal** (separate from carrier demurrage) when a container sits at the terminal beyond a threshold. Common at major US gateways like the Ports of LA and Long Beach. ```json theme={null} { "type": "extended_dwell_time", "amount": 300.00, "currency_code": "USD" } ``` Covers the cost of a physical or non-intrusive (VACIS) inspection by CBP or USDA. Exam fees are typically paid to the terminal or a government-approved exam facility. Amounts vary widely β€” from a few hundred to several thousand dollars depending on the exam type. ```json theme={null} { "type": "exam", "amount": 450.00, "currency_code": "USD" } ``` A combined total of all fees at the terminal, reported as a single line item. Some terminals report only a total rather than individual fee breakdowns. If you see a `total` fee in the array alongside individual line items, filter it out when summing to avoid double-counting. ```json theme={null} { "type": "total", "amount": 2000.00, "currency_code": "USD" } ``` A fee that Terminal49 could not map to a specific type. ```json theme={null} { "type": "other", "amount": 75.00, "currency_code": "USD" } ``` ## Full example: container with multiple holds and fees ```json theme={null} { "holds_at_pod_terminal": [ { "name": "customs", "status": "hold", "description": "CBP HOLD" }, { "name": "freight", "status": "hold", "description": null } ], "fees_at_pod_terminal": [ { "type": "demurrage", "amount": 850.00, "currency_code": "USD" }, { "type": "exam", "amount": 450.00, "currency_code": "USD" } ] } ``` In this example, the container has two active holds (`customs` and `freight`) and two fees. Both holds must be resolved before the container can be released. The demurrage fee will continue increasing daily until the container is picked up. ## Getting notified when holds or fees change Subscribe to the `container.updated` webhook to run your release-readiness check in real time whenever holds or fees change. The `changeset` on the `container_updated_event` shows the old value and new value side by side β€” old first, new second. For full details on setting up webhooks, see [Webhooks](/api-docs/in-depth-guides/webhooks). A customs hold appeared on the container: ```json theme={null} { "changeset": { "holds_at_pod_terminal": [ [], [ { "name": "customs", "status": "hold", "description": "CBP HOLD" } ] ] } } ``` The customs hold was lifted β€” the container is now clear: ```json theme={null} { "changeset": { "holds_at_pod_terminal": [ [ { "name": "customs", "status": "hold", "description": "CBP HOLD" } ], [] ] } } ``` A pending hold escalated to an active hold: ```json theme={null} { "changeset": { "holds_at_pod_terminal": [ [ { "name": "customs", "status": "pending", "description": null } ], [ { "name": "customs", "status": "hold", "description": "CBP HOLD" } ] ] } } ``` Demurrage increased as another day accrued: ```json theme={null} { "changeset": { "fees_at_pod_terminal": [ [ { "type": "demurrage", "amount": 850.00, "currency_code": "USD" } ], [ { "type": "demurrage", "amount": 1250.00, "currency_code": "USD" } ] ] } } ``` ## Edge cases * **Empty arrays mean no holds or fees.** An empty `holds_at_pod_terminal: []` or `fees_at_pod_terminal: []` is the normal state for most containers. Do not treat it as missing data or an error. **Avoid double-counting when `total` is present.** Some terminals report a `total` fee alongside individual line items. Filter it out before summing: ```javascript theme={null} const lineItems = container.fees_at_pod_terminal.filter(f => f.type !== 'total'); const totalAmount = lineItems.reduce((acc, f) => acc + f.amount, 0); ``` **Fee amount of `0` is valid.** A fee amount of `0` means the terminal reported the fee type but has not yet calculated or posted the dollar amount. This is common for demurrage in the first day or two after discharge. Poll the container or wait for the next `container.updated` event. **The `description` field is raw terminal text.** The `description` on hold objects is unstructured text scraped directly from the terminal. It is useful context for humans but should not be used for programmatic decision-making. Use the `name` field to drive automation logic. ## Frequently asked questions Check two fields together: `available_for_pickup` must be `true` **and** the `holds_at_pod_terminal` array must have no items with `status: "hold"`. See the [decision logic and code example](#determine-if-a-container-is-ready-for-pickup) above. 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. 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. Terminal data is sourced from multiple systems on varying schedules. A hold can clear before the terminal updates `available_for_pickup`, or vice versa. Wait for the next `container.updated` webhook or poll the container again. Treat `available_for_pickup: true` with an empty holds array as the definitive readiness signal. Yes. The `holds_at_pod_terminal` and `fees_at_pod_terminal` fields report data regardless of whether the container is at a port terminal or an inland rail destination. The field names reference `pod_terminal` for historical reasons, but the same readiness logic applies in both scenarios. Some terminals report a `total` fee alongside individual line items. Filter it out before summing: ```javascript theme={null} const lineItems = container.fees_at_pod_terminal.filter(f => f.type !== 'total'); const totalAmount = lineItems.reduce((acc, f) => acc + f.amount, 0); ``` ## Related guides How `available_for_pickup` and `current_status` are derived Subscribe to `container.updated` events When terminal data was captured Inland rail moves and container tracking at rail destinations # Including Resources Source: https://terminal49.com/docs/api-docs/in-depth-guides/including-resources Throughout the documentation you will notice that many of the endpoints include a `relationships` object inside of the `data` attribute. For example, if you are [requesting a container](/api/4c6091811c4e0-get-a-container) the relationships will include `shipment`, and possibly `pod_terminal` and `transport_events` If you want to load the `shipment` and `pod_terminal` without making any additional requests you can add the query parameter `include` and provide a comma delimited list of the related resources: ``` containers/{id}?include=shipment,pod_terminal ``` You can even traverse the relationships up or down. For example if you wanted to know the port of lading for the container you could get that with: ``` containers/{id}?include=shipment,shipment.port_of_lading ``` # MCP Server Quickstart Source: https://terminal49.com/docs/api-docs/in-depth-guides/mcp Full setup guide for the Terminal49 MCP server # MCP Server Quickstart This guide covers everything you need to connect Claude or Cursor to Terminal49's container tracking data via MCP. Just want to get started fast? See [MCP Overview](/mcp/home) for a 5-minute setup. ## Prerequisites Before you begin, make sure you have: A Terminal49 account with API access A `T49_API_TOKEN` from the [dashboard](https://app.terminal49.com/developers/api-keys) Required if running the MCP server locally Claude Desktop or Cursor IDE **Technical Details:** * **MCP SDK**: `@modelcontextprotocol/sdk ^1.26.0` * **TypeScript SDK**: `@terminal49/sdk` * **Runtime**: Node.js 18+ *** ## Transports | Transport | Endpoint | Best For | | ----------------- | ------------------------------ | -------------------------------- | | HTTP (streamable) | `POST /api/mcp` or `POST /mcp` | Serverless, short-lived requests | **Authentication**: API token only (OAuth not required for this release).\ Pass `Authorization: Bearer ` or `Authorization: Token `.\ Server falls back to `T49_API_TOKEN` environment variable. Claude Desktop and Cursor use the HTTP transport. For hosted production usage, use Streamable HTTP at `/mcp`. For hosted OAuth implementation planning, see [Hosted HTTP OAuth Requirements](/mcp/hosted-http-oauth-requirements) and [Hosted HTTP OAuth Test Plan](/mcp/hosted-http-oauth-test-plan). *** ## Configure Your MCP Client ### Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Edit `%APPDATA%\Claude\claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Edit `~/.config/Claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ### Cursor IDE Add to your Cursor settings: ```json theme={null} { "mcp": { "servers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } } ``` ### Local stdio (Development) For local development without a hosted server: ```json theme={null} { "mcpServers": { "terminal49": { "command": "node", "args": ["/path/to/API/packages/mcp/dist/index.js"], "env": { "T49_API_TOKEN": "your_token_here" } } } } ``` Build the MCP server first: `cd packages/mcp && npm install && T49_SDK_SOURCE=published npm run sdk:setup && npm run build` Use published SDK by default: ```bash theme={null} cd packages/mcp T49_SDK_SOURCE=published npm run sdk:setup ``` Use local SDK build during development: ```bash theme={null} cd packages/mcp T49_SDK_SOURCE=local npm run sdk:setup ``` *** ## Test Your Setup Once configured, verify everything works: Close and reopen Claude Desktop or Cursor to load the new config. > "List the tools available in the Terminal49 MCP server." Claude should respond with a list of 10 tools including `search_container`, `track_container`, and list tools. > "Using the Terminal49 MCP server, search for container TCLU1234567 and summarize its status." If configured correctly, Claude will call `search_container` and return container details. > "Using Terminal49, find container CAIU1234567, check its demurrage risk, and tell me if I need to pick it up urgently." Claude should chain multiple tools together to answer. Need test container numbers? See [Test Numbers](/api-docs/useful-info/test-numbers) for containers you can use during development. *** ## Troubleshooting | Symptom | Likely Cause | How to Fix | | ------------------------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | | "Cannot connect to MCP server" | Wrong URL or config path | Confirm URL is `https://mcp.terminal49.com/mcp` and config file path matches your OS | | `401 Unauthorized` | Missing or invalid token | Create a new API token in [dashboard](https://app.terminal49.com/developers/api-keys); ensure `Authorization: Bearer ` header is set | | `429 Too Many Requests` | Rate limit exceeded | See [Rate Limiting](/api-docs/in-depth-guides/rate-limiting); use webhooks instead of polling | | Tools list is empty | Config not loaded | Restart Claude/Cursor; check MCP inspector for errors | | "Tool not found" | Typo in tool name | Use exact names: `search_container`, `get_container`, etc. | | Slow responses | Large data requests | Use `include` parameter to load only what you need | If using the hosted server, check your Terminal49 dashboard for API logs. If running locally: ```bash theme={null} cd packages/mcp T49_API_TOKEN=your_token npm run mcp:stdio 2>&1 | head -20 ``` *** ## MCP Capabilities ### Tools (10) | Tool | Description | Parameters | | -------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | | `search_container` | Find containers by number, BL, booking, or ref | `query: string` | | `track_container` | Start tracking a container | `number`, `numberType?`, `scac?`, `refNumbers?` | | `get_container` | Get container with optional includes | `id: uuid`, `include?: ['shipment', 'pod_terminal', 'transport_events']` | | `get_shipment_details` | Get shipment and containers | `id: uuid`, `include_containers?: boolean` | | `get_container_transport_events` | Get event timeline | `id: uuid` | | `get_supported_shipping_lines` | List carriers with SCAC codes | `search?: string` | | `get_container_route` | Get multi-leg routing (paid feature) | `id: uuid` | | `list_shipments` | List shipments with filters + pagination | `status?`, `port?`, `carrier?`, `updated_after?`, `include_containers?`, `page?`, `page_size?` | | `list_containers` | List containers with filters + pagination | `status?`, `port?`, `carrier?`, `updated_after?`, `include?`, `page?`, `page_size?` | | `list_tracking_requests` | List tracking requests with filters | `filters?`, `status?`, `request_type?`, `page?`, `page_size?` | ### Prompts (3) | Prompt | Description | Arguments | | ----------------- | ----------------------- | ------------------------------ | | `track-shipment` | Quick tracking workflow | `container_number`, `carrier?` | | `check-demurrage` | Demurrage risk analysis | `container_id` | | `analyze-delays` | Journey delay analysis | `container_id` | ### Resources (2) | URI | Description | | -------------------------------------- | -------------------------- | | `terminal49://container/{id}` | Container data as resource | | `terminal49://docs/milestone-glossary` | Event/milestone reference | For detailed examples and response formats, see [MCP Overview β†’ Tools Reference](/mcp/home#tools-reference). *** ## SDK Usage The TypeScript SDK provides the same capabilities as MCP tools, plus additional APIs not yet exposed via MCP. ```bash theme={null} npm install @terminal49/sdk ``` ```typescript theme={null} import { Terminal49Client } from '@terminal49/sdk'; const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, defaultFormat: 'mapped' }); // Get container with shipment and terminal const container = await client.containers.get( 'container-uuid', ['shipment', 'pod_terminal'] ); // Search for containers const results = await client.search('CAIU1234567'); // List shipments with filters (not available via MCP) const shipments = await client.shipments.list({ status: 'in_transit', carrier: 'MAEU' }); ``` ### Response Formats | Format | Description | | -------- | ------------------------------------------------------------ | | `raw` | JSON:API response with `data`, `attributes`, `relationships` | | `mapped` | Simplified, camelCase objects with IDs resolved | | `both` | `{ raw, mapped }` for debugging | **Raw format:** ```json theme={null} { "data": { "type": "container", "id": "abc-123", "attributes": { "container_number": "CAIU1234567", "available_for_pickup": true } } } ``` **Mapped format:** ```json theme={null} { "id": "abc-123", "containerNumber": "CAIU1234567", "availableForPickup": true } ``` *** ## Deployment ### Vercel (Production) The `vercel.json` configures the MCP server: ```json theme={null} { "buildCommand": "cd packages/mcp && npm ci && npm run build", "functions": { "api/mcp.ts": { "maxDuration": 30, "memory": 1024 } }, "rewrites": [ { "source": "/mcp", "destination": "/api/mcp" } ] } ``` ### Environment Variables | Variable | Required | Description | | ------------------------- | -------- | -------------------------------------------------------------- | | `T49_API_TOKEN` | Yes | Terminal49 API token | | `T49_API_BASE_URL` | No | Override API URL (default: `https://api.terminal49.com/v2`) | | `T49_MCP_ALLOWED_HOSTS` | No | Comma-separated host allowlist for request Host validation | | `T49_MCP_ALLOWED_ORIGINS` | No | Comma-separated origin allowlist for request Origin validation | *** ## Testing Locally ```bash theme={null} # Build the MCP server cd packages/mcp npm install npm run build # Test tools/list echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | T49_API_TOKEN=your_token npm run mcp:stdio # Test search_container echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"search_container","arguments":{"query":"CAIU1234567"}},"id":2}' | T49_API_TOKEN=your_token npm run mcp:stdio # Test the hosted endpoint curl -X POST https://mcp.terminal49.com/mcp \ -H "Authorization: Bearer $T49_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}' ``` *** ## Related Guides * [MCP Overview](/mcp/home) – Quick start and tools reference * [Rate Limiting](/api-docs/in-depth-guides/rate-limiting) – API limits (same for MCP) * [Test Numbers](/api-docs/useful-info/test-numbers) – Containers for testing * [Webhooks](/api-docs/in-depth-guides/webhooks) – Real-time updates * [API Data Sources](/api-docs/useful-info/api-data-sources-availability) – Data freshness and coverage # Quick Start Guide Source: https://terminal49.com/docs/api-docs/in-depth-guides/quickstart ## Before You Begin You'll need a four things to get started. 1. **A Bill of Lading (BOL) number.** This is issued by your carrier. BOL numbers are found on your [bill of lading](https://en.wikipedia.org/wiki/Bill_of_lading) document. Ideally, this will be a shipment that is currently on the water or in terminal, but this is not necessary. 2. **The SCAC of the carrier that issued your bill of lading.** The Standard Carrier Alpha Code of your carrier is used to identify carriers in computer systems and in shipping documents. You can learn more about these [here](https://en.wikipedia.org/wiki/Standard_Carrier_Alpha_Code). 3. **A Terminal49 Account.** If you don't have one yet, [sign up here.](https://app.terminal49.com/register) 4. **An API key.** Sign in to your Terminal49 account and go to your [developer portal page](https://app.terminal49.com/developers) to get your API key. Not sure which SCAC to use? The [Auto-Detect Carrier](/api-docs/in-depth-guides/auto-detect-carrier) API can identify it from your tracking number. ## Track a Shipment You can try this using the embedded request maker below, or using Postman. 1. Try it below. Click "Headers" and replace YOUR\_API\_KEY with your API key. In the authorization header value. 2. Enter a value for theΒ `request_number`Β andΒ `scac`. The request number has to be a shipping line booking or master bill of lading number. The SCAC has to be a shipping line scac (see data sources to get a list of valid SCACs) Note that you can also access sample code, include a cURL template, by clicking the "Code Generation" tab in the Request Maker. ```json http theme={null} { "method": "post", "url": "https://api.terminal49.com/v2/tracking_requests", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" }, "body": "{\r\n \"data\": {\r\n \"attributes\": {\r\n \"request_type\": \"bill_of_lading\",\r\n \"request_number\": \"\",\r\n \"scac\": \"\"\r\n },\r\n \"type\": \"tracking_request\"\r\n }\r\n}" } ``` ## Check Your Tracking Request Succeeded We have not yet set up a webook to receive status updates from the Terminal49 API, so we will need to manually poll to check if the Tracking Request has succeeded or failed. > ### Tracking Request Troubleshooting > > The most common issue people encounter is that they are entering the wrong number. > > Please check that you are entering the Bill of Lading number, booking number, or container number and not internal reference at your company or by your frieght forwarder. You can the number you are supplying by going to a carrier's website and using their tools to track your shipment using the request number. If this works, and if the SCAC is supported by T49, you should able to track it with us. > > You can always email us at [support@terminal49.com](mailto:support@terminal49.com) if you have persistent issues. \*\* Try it below. Click "Headers" and replace `` with your API key.\*\* ```json http theme={null} { "method": "get", "url": "https://api.terminal49.com/v2/tracking_requests", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" } } ``` ## List your Tracked Shipments If your tracking request was successful, you will now be able to list your tracked shipments. **Try it below. Click "Headers" and replace YOUR\_API\_KEY with your API key.** Sometimes it may take a while for the tracking request to show up, but usually no more than a few minutes. If you had trouble adding your first shipment, try adding a few more. ```json http theme={null} { "method": "get", "url": "https://api.terminal49.com/v2/shipments", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" } } ``` ## List all your Tracked Containers You can also list out all of your containers, if you'd like to track at that level. Try it after replacing `` with your API key. ```json http theme={null} { "method": "get", "url": "https://api.terminal49.com/v2/containers", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" } } ``` ## Listening for Updates with Webhooks The true power of Terminal49's API is that it is asynchronous. You can register a Webhook, which is essentially a callback URL that our systems HTTP Post to when there are updates. To try this, you will need to first set up a URL on the open web to receive POST requests. Once you have done this, you'll be able to receive status updates from containers and shipments as they happen, which means you don't need to poll us for updates; we'll notify you. \*\* Try it below. Click "Headers" and replace YOUR\_API\_KEY with your API key.\*\* Once this is done, any changes to shipments and containers you're tracking in step 2 will now be sent to your webhook URL as Http POST Requests. View the "Code Generation" button to see sample code. ```json http theme={null} { "method": "post", "url": "https://api.terminal49.com/v2/webhooks", "headers": { "Content-Type": "application/vnd.api+json", "Authorization": "Token YOUR_API_KEY" }, "body": "{\r\n \"data\": {\r\n \"type\": \"webhook\",\r\n \"attributes\": {\r\n \"url\": \"https:\/\/webhook.site\/\",\r\n \"active\": true,\r\n \"events\": [\r\n \"*\"\r\n ]\r\n }\r\n }\r\n}" } ``` # Integrate Rail Container Tracking Data Source: https://terminal49.com/docs/api-docs/in-depth-guides/rail-integration-guide This guide provides a comprehensive, step-by-step approach for integrating North American Class-1 rail container tracking data into your systems. Whether you are a shipper or a logistics service provider, this guide will help you track all your rail containers via a single API. This is a technical article about rail data within Terminal49's API and DataSync. For a broader overview, including the reasons why you'd want rail visibility and how to use it in the Terminal49 dashboard, [read our announcement post](https://www.terminal49.com/blog/launching-north-american-intermodal-rail-visibility-on-terminal49/). ## Table of Contents * [Supported Rail Carriers](#supported-rail-carriers) * [Supported Rail Events and Data Attributes](#supported-rail-events-and-data-attributes) * [Rail-specific Transport Events](#rail-specific-transport-events) * [Webhook Notifications](#webhook-notifications) * [Rail Container Attributes](#rail-container-attributes) * [Integration Methods](#integration-methods) * [Integration via API](#a-integration-via-api) * [Integration via DataSync](#b-integration-via-datasync) ## Supported Rail Carriers Terminal49 container tracking platform integrates with all North American Class-1 railroads that handle container shipping, providing comprehensive visibility into your rail container movements. * BNSF Railway * Canadian National Railway (CN) * Canadian Pacific Railway (CP) * CSX Transportation * Norfolk Southern Railway (NS) * Union Pacific Railroad (UP) By integrating with these carriers, Terminal49 ensures that you have direct access to critical tracking data, enabling better decision-making and operational efficiency. ## Supported Rail Events and Data Attributes Terminal49 seamlessly tracks your containers as they go from container ship, to ocean terminal, to rail carrier. We provide a [set of Transport Events](#webhook-notifications) that let you track the status of your containers as they move through the rail system. You can be notified by webhook whenever these events occur. We also provide a set of attributes [on the container model](/api-docs/api-reference/containers/get-a-container) that let you know the current status of your container at any given time, as well as useful information such as ETA, pickup facility, and availability information. For details on hold types, fee types, and how to determine release readiness at the port or an inland destination, see [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees). ### Rail-Specific Transport Events There are several core Transport Events that occur on most rail journeys. Some rail carriers do not share all events, but in general these are the key events for a container. ```mermaid theme={null} graph LR A[Rail Loaded] --> B[Rail Departed] B --> C[Arrived at Inland Destination] C --> D[Rail Unloaded] D --> G[Available for Pickup] G --> E[Full Out] E --> F[Empty Return] ``` `Available for Pickup`, `Full Out` and `Empty Return` are not specific to rail, but are included here since they are a key part of the rail journey. ### Webhook Notifications Terminal49 provides webhook notifications to keep you updated on key Transport Events in a container's rail journey. These notifications allow you to integrate near real-time tracking data directly into your applications. Here's a list of the rail-specific events which support webhook notifications: | Transport Event | Webhook Notification | Description | Example | | ----------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Rail Loaded | `container.transport.rail_loaded` | The container is loaded onto a railcar. | Example | | Rail Departed | `container.transport.rail_departed` | The container departs on the railcar (not always from port of discharge). | Example | | Rail Arrived | `container.transport.rail_arrived` | The container arrives at a rail terminal (not always at the destination terminal). | Example | | Arrived At Inland Destination | `container.transport.arrived_at_inland_destination` | The container arrives at the destination terminal. | Example | | Rail Unloaded | `container.transport.rail_unloaded` | The container is unloaded from a railcar. | Example | There's also a set of events that are triggered when the status of the container at the destination rail terminal changes. For containers without rail, they would have been triggered at the ocean terminal. | Transport Event | Webhook Notification | Description | Example | | --------------- | ------------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | Full Out | `container.transport.full_out` | The full container leaves the rail terminal. | Example | | Empty In | `container.transport.empty_in` | The empty container is returned to the terminal. | Example | Finally, we have a webhook notifications for when the destination ETA changes. | Transport Event | Webhook Notification | Description | Example | | ----------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Estimated Destination Arrival | `container.transport.estimated.arrived_at_inland_destination` | Estimated time of arrival for the container at the destination rail terminal. | Example | Integrate these notifications by subscribing to the webhooks and handling the incoming data to update your systems. #### Rail Container Attributes The following are new attributes that are specific to rail container tracking. * **pod\_rail\_loaded\_at**: Time when the container is loaded onto a railcar at the POD. * **pod\_rail\_departed\_at**: Time when the container departs from the POD. * **ind\_eta\_at**: Estimated Time of Arrival at the inland destination. * **ind\_ata\_at**: Actual Time of Arrival at the inland destination. * **ind\_rail\_unloaded\_at**: Time when the container is unloaded from rail at the inland destination. * **ind\_facility\_lfd\_on**: Last Free Day for demurrage charges at the inland destination terminal. * **pod\_rail\_carrier\_scac**: SCAC code of the rail carrier that picks up the container from the POD (this could be different than the rail carrier that delivers to the inland destination). * **ind\_rail\_carrier\_scac**: SCAC code of the rail carrier that delivers the container to the inland destination. These attributes can be found on [container objects](/api-docs/api-reference/containers/get-a-container). ## Integration Methods There are two methods to integrate Terminal49's rail tracking data programmatically: via API and DataSync. ### A. Integration via API Terminal49 provides a robust API that allows you to programmatically access rail container tracking data and receive updates via webhooks. You will receive rail events and attributes alongside events and attributes from the ocean terminal and carrier. [Here's a step-by-step guide to get started](/api-docs/getting-started/start-here) ### B. Integration via DataSync Terminal49's DataSync service automatically syncs up-to-date tracking data with your system. The rail data will be in the same tables alongside the ocean terminal and carrier data. [Learn more about DataSync](/datasync/overview) # Rate Limiting Source: https://terminal49.com/docs/api-docs/in-depth-guides/rate-limiting ## Overview Terminal49 API implements rate limiting to ensure fair usage and maintain service quality for all users. ## Rate Limit Details * **Limit**: 100 requests per minute per account * **Scope**: Applied per API key/account * **Window**: Rolling 60-second window ## Rate Limit Response When you exceed the rate limit, the API will return: **HTTP Status Code**: `429 Too Many Requests` **Response Headers**: * `Retry-After`: Number of seconds to wait before making another request **Response Body**: ```json theme={null} { "errors": [ { "status": "429", "title": "Too Many Requests", "detail": "Your account has exceeded its API rate limit. Please reduce request frequency or contact support to increase your limit. Consider using webhooks for real-time updates instead of polling." } ] } ``` ## Best Practices ### 1. Use Webhooks Instead of Polling The most effective way to avoid rate limits is to use **webhooks** for real-time updates instead of repeatedly polling the API: * Configure webhooks to receive push notifications when shipment data changes * Eliminates the need for frequent polling * Provides instant updates without consuming your rate limit * See the [Webhooks](/api-docs/api-reference/webhooks) section for setup instructions ### 2. Implement Exponential Backoff If you receive a `429` response: 1. Check the `Retry-After` header 2. Wait for the specified number of seconds 3. Implement exponential backoff for subsequent failures 4. Don't retry immediately, as this will consume your limit further ### 3. Batch Your Requests * Use list endpoints with filtering instead of multiple individual requests * Leverage the [`include` parameter](/api-docs/in-depth-guides/including-resources) to fetch related resources in a single request * Cache responses when appropriate to reduce redundant calls ### 4. Monitor Your Usage * Track your request patterns * Identify and optimize high-frequency operations * Consider spreading requests over time rather than bursting ## Need a Higher Limit? If your use case requires a higher rate limit: 1. **Evaluate webhook usage first** - Most polling use cases can be replaced with webhooks 2. **Contact support** at [support@terminal49.com](mailto:support@terminal49.com) 3. **Provide details** about your use case and expected request volume 4. **Our team will work with you** to find an appropriate solution ## Example: Handling Rate Limits Here's an example of how to properly handle rate limit responses in Python: ```python theme={null} import time import requests def make_request_with_retry(url, headers, max_retries=3): """ Make an API request with automatic retry on rate limit. Args: url: The API endpoint URL headers: Request headers including Authorization max_retries: Maximum number of retry attempts Returns: Response object if successful Raises: Exception: If max retries exceeded """ for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code == 429: # Get the retry-after value from header (default to 60 seconds) retry_after = int(response.headers.get('Retry-After', 60)) print(f"Rate limited. Waiting {retry_after} seconds...") time.sleep(retry_after) continue # Return response for any other status code return response raise Exception("Max retries exceeded") # Example usage headers = { 'Authorization': 'Token YOUR_API_KEY' } response = make_request_with_retry( 'https://api.terminal49.com/v2/shipments', headers ) ``` ## Tips for High-Volume Applications If you're building a high-volume application: * **Design for webhooks from the start**: Don't rely on polling for data updates * **Implement request queuing**: Spread your requests evenly across the rate limit window * **Use pagination efficiently**: Fetch larger pages less frequently rather than small pages frequently * **Cache aggressively**: Store and reuse data that doesn't change frequently * **Monitor rate limit headers**: Some APIs provide headers indicating remaining quota (check our response headers) # Vessel and Container Route Data Source: https://terminal49.com/docs/api-docs/in-depth-guides/routing This guide explains how to access detailed container routes and vessel positions data (historical and future positions) using Terminal49 APIs. This is a technical article describing how to use our Routing Data feature, using the map as an example. Routing Data (Container Map GeoJSON API) is a paid feature. These APIs are subject to additional terms of usage and pricing. If you are interested in using these APIs, please contact [sales@terminal49.com](mailto:sales@terminal49.com). ## Table of Contents * [Overview](#overview) * [Getting Started](#getting-started) * [Understanding the Response](#understanding-the-response) * [GeoJSON FeatureCollection Structure](#geojson-featurecollection-structure) * [Feature Types](#feature-types) * [Port](#port) * [Current Vessel](#current-vessel) * [Past Vessel Locations](#past-vessel-locations) * [Estimated Full Leg](#estimated-full-leg) * [Estimated Partial Leg](#estimated-partial-leg) * [Building Your Map](#building-your-map) * [Use Cases](#use-cases) * [Recommendations and Best Practices](#recommendations-and-best-practices) * [Frequently Asked Questions](#frequently-asked-questions) ## Overview The `GET /v2/containers/{id}/map_geojson` endpoint provides all the map-related data for a container in a single GeoJSON response. The endpoint returns a GeoJSON FeatureCollection containing: * **Port locations** (Point geometries): Port of lading (POL), port of discharge (POD), and transshipment ports (TS1, TS2, etc.) * **Current vessel location** (Point geometry): The current position of the vessel if the container is currently at sea * **Past vessel paths** (LineString geometries): Historical positions of vessels for completed and in-progress legs of the journey * **Estimated future paths** (LineString geometries): Predicted vessel routes for upcoming or in-progress legs Example of a shipment map ## Getting Started To retrieve the map data for a container, make a simple GET request to the endpoint: ```shell Request theme={null} curl --request GET \ --url https://api.terminal49.com/v2/containers/{id}/map_geojson \ --header "Authorization: Token YOUR_API_TOKEN" ``` The response is a standard GeoJSON FeatureCollection that can be directly used with most mapping libraries (Leaflet, Mapbox GL, Google Maps, etc.). ```json theme={null} { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 100.896831042, 13.065302386 ] }, "properties": { "feature_type": "port", "ports_sequence": 1, "ports_total": 3, "label": "POL", "name": "Laem Chabang", // ... more properties } }, { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [ 100.868768333, 13.07306 ], [ 100.839155, 13.079318333 ], // ... more coordinates [ 118.03862, 24.440998333 ] ] }, "properties": { "feature_type": "past_vessel_locations", "vessel_id": "87a12f43-766c-4078-89bc-ac6595082f7b", // ... more path properties } }, // ... more features ] } ``` ## Understanding the Response ### GeoJSON FeatureCollection Structure The response follows the [GeoJSON specification](https://geojson.org/) and contains: * `type`: Always `"FeatureCollection"` * `features`: An array of GeoJSON Feature objects, each representing a map element (port, vessel, or route path) Each feature contains: * `type`: Always `"Feature"` * `geometry`: A GeoJSON geometry object (Point or LineString) * `properties`: An object containing metadata specific to the feature type ### Feature Types The `properties.feature_type` field identifies what each feature represents. The following feature types are available: #### Port 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.). ```json theme={null} { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 100.896831042, 13.065302386 ] }, "properties": { "feature_type": "port", "ports_sequence": 1, "ports_total": 3, "location_id": "c5adae24-6fd4-4720-8813-976cf206feb1", "location_type": "Port", "name": "Laem Chabang", "state_abbr": "20", "state": null, "country_code": "TH", "country": "Thailand", "time_zone": "Asia/Bangkok", "inbound_eta_at": null, "inbound_ata_at": null, "outbound_etd_at": null, "outbound_atd_at": "2025-11-08T00:44:52Z", "label": "POL", "updated_at": "2025-12-11T09:01:08Z" } } ``` | Property | Type | Description | | ----------------- | -------------- | ------------------------------------------------------------------- | | `feature_type` | string | Always `"port"` | | `ports_sequence` | integer | The sequence number of this port in the route (1 = POL, last = POD) | | `ports_total` | integer | Total number of ports in the route | | `location_id` | string | Unique identifier for the port location | | `location_type` | string | Always `"Port"` | | `name` | string | Name of the port | | `state_abbr` | string \| null | State abbreviation (if applicable) | | `state` | string \| null | State name (if applicable) | | `country_code` | string | ISO country code | | `country` | string | Country name | | `time_zone` | string | IANA timezone identifier | | `label` | string | Port label: `"POL"`, `"POD"`, or `"TS1"`, `"TS2"`, etc. | | `inbound_eta_at` | string \| null | Estimated time of arrival (ISO 8601) | | `inbound_ata_at` | string \| null | Actual time of arrival (ISO 8601) | | `outbound_etd_at` | string \| null | Estimated time of departure (ISO 8601) | | `outbound_atd_at` | string \| null | Actual time of departure (ISO 8601) | | `updated_at` | string \| null | Last update timestamp from the shipment (ISO 8601) | #### Current Vessel 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. ```json theme={null} { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -131.128473333, 31.023033333 ] }, "properties": { "feature_type": "current_vessel", "ports_sequence": 2, "vessel_id": "93fc5dce-4c7f-4089-bd28-f20cd9202ab0", "vessel_name": "ZIM BANGKOK", "vessel_imo": "9936525", "voyage_number": "13E", "vessel_location_timestamp": "2025-12-11T11:46:03Z", "vessel_location_heading": 108, "vessel_location_speed": 21, "departure_port_id": "ed64d446-9098-420c-ab08-c127e62509fe", "departure_port_name": "Xiamen", "departure_port_state_abbr": "FJ", "departure_port_state": null, "departure_port_country_code": "CN", "departure_port_country": "China", "departure_port_label": "TS1", "departure_port_atd": "2025-11-19T16:00:00Z", "departure_port_time_zone": "Asia/Shanghai", "arrival_port_id": "6129528d-846e-4571-ae16-b5328a4285ab", "arrival_port_name": "Savannah", "arrival_port_state_abbr": "GA", "arrival_port_state": "Georgia", "arrival_port_country_code": "US", "arrival_port_country": "United States", "arrival_port_label": "POD", "arrival_port_eta": "2025-12-31T05:00:00Z", "arrival_port_time_zone": "America/New_York" } } ``` | Property | Type | Description | | ----------------------------- | -------------- | ----------------------------------------------------- | | `feature_type` | string | Always `"current_vessel"` | | `ports_sequence` | integer | Sequence number of the departure port for this leg | | `vessel_id` | string | Unique identifier for the vessel | | `vessel_name` | string | Name of the vessel | | `vessel_imo` | string | IMO number of the vessel | | `voyage_number` | string \| null | Voyage number for this leg | | `vessel_location_timestamp` | string | Timestamp of the vessel position (ISO 8601) | | `vessel_location_heading` | number \| null | Vessel heading in degrees (0-360) | | `vessel_location_speed` | number \| null | Vessel speed in knots | | `departure_port_id` | string | ID of the port the vessel departed from | | `departure_port_name` | string | Name of the departure port | | `departure_port_state_abbr` | string \| null | State abbreviation of departure port | | `departure_port_state` | string \| null | State name of departure port | | `departure_port_country_code` | string | Country code of departure port | | `departure_port_country` | string | Country name of departure port | | `departure_port_label` | string | Label of departure port (POL, POD, TS1, etc.) | | `departure_port_atd` | string \| null | Actual time of departure from the port (ISO 8601) | | `departure_port_time_zone` | string | Timezone of departure port | | `arrival_port_id` | string \| null | ID of the next port the vessel is heading to | | `arrival_port_name` | string \| null | Name of the arrival port | | `arrival_port_state_abbr` | string \| null | State abbreviation of arrival port | | `arrival_port_state` | string \| null | State name of arrival port | | `arrival_port_country_code` | string \| null | Country code of arrival port | | `arrival_port_country` | string \| null | Country name of arrival port | | `arrival_port_label` | string \| null | Label of arrival port (POL, POD, TS1, etc.) | | `arrival_port_eta` | string \| null | Estimated time of arrival at the next port (ISO 8601) | | `arrival_port_time_zone` | string \| null | Timezone of arrival port | #### Past Vessel Locations 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. ```json theme={null} { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [ 100.868768333, 13.07306 ], [ 100.839155, 13.079318333 ], // ... many more coordinates [ 118.03862, 24.440998333 ] ] }, "properties": { "feature_type": "past_vessel_locations", "ports_sequence": 1, "vessel_id": "87a12f43-766c-4078-89bc-ac6595082f7b", "start_time": "2025-11-08T00:44:52Z", "end_time": "2025-11-15T16:00:00Z", "point_count": 546, "outbound_atd_at": "2025-11-08T00:44:52Z", "inbound_ata_at": "2025-11-15T16:00:00Z", "inbound_eta_at": null } } ``` | Property | Type | Description | | ----------------- | -------------- | ------------------------------------------------------------ | | `feature_type` | string | Always `"past_vessel_locations"` | | `ports_sequence` | integer | Sequence number of the departure port for this leg | | `vessel_id` | string | Unique identifier for the vessel that traveled this path | | `start_time` | string | Start timestamp of the path (ISO 8601) | | `end_time` | string | End timestamp of the path (ISO 8601) | | `point_count` | integer | Number of coordinate points in the LineString | | `outbound_atd_at` | string \| null | Actual time of departure from the origin port (ISO 8601) | | `inbound_ata_at` | string \| null | Actual time of arrival at the destination port (ISO 8601) | | `inbound_eta_at` | string \| null | Estimated time of arrival at the destination port (ISO 8601) | #### Estimated Full Leg 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. ```json theme={null} { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [55.059917502, 24.987353081], [55.234, 24.856], [56.123, 24.567], // ... intermediate estimated points [79.851136851, 6.942742853] ] }, "properties": { "feature_type": "estimated_full_legs", "ports_sequence": 2, "previous_port_id": "94892d07-ef8f-4f76-a860-97a398c2c177", "next_port_id": "818ef299-aed3-49c9-b3f7-7ee205f697f6", "point_count": 87 } } ``` | Property | Type | Description | | ------------------ | ------- | -------------------------------------------------- | | `feature_type` | string | Always `"estimated_full_legs"` | | `ports_sequence` | integer | Sequence number of the departure port for this leg | | `previous_port_id` | string | ID of the origin port | | `next_port_id` | string | ID of the destination port | | `point_count` | integer | Number of coordinate points in the LineString | #### Estimated Partial Leg 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. ```json theme={null} { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [ -131.128473333, 31.023033333 ], [ -130.9177, 30.67224 ], // ... many more coordinates [ -80.91232, 32.03728 ] ] }, "properties": { "feature_type": "estimated_partial_leg", "ports_sequence": 2, "current_port_id": "ed64d446-9098-420c-ab08-c127e62509fe", "next_port_id": "6129528d-846e-4571-ae16-b5328a4285ab", "point_count": 364 } } ``` | Property | Type | Description | | ----------------- | ------- | -------------------------------------------------- | | `feature_type` | string | Always `"estimated_partial_leg"` | | `ports_sequence` | integer | Sequence number of the departure port for this leg | | `current_port_id` | string | ID of the port the vessel departed from | | `next_port_id` | string | ID of the next port the vessel is heading to | | `point_count` | integer | Number of coordinate points in the LineString | **Note:** This feature is only present when there is a `current_vessel` feature. The LineString starts from the vessel's current position (which matches the `current_vessel` feature coordinates) and extends to the next port. ## Building Your Map To visualize a container's journey using the GeoJSON response on your own map (similar to [the embeddable map](/api-docs/in-depth-guides/terminal49-map)): 1. **Load the GeoJSON data** into your mapping library (Leaflet, Mapbox GL, Google Maps, etc.) 2. **Filter features by type** to style them differently: * **Ports**: Display as markers with labels (POL, POD, TS1, etc.) * **Current vessel**: Display as a special marker (e.g., a ship icon) with vessel information * **Past vessel locations**: Display as solid lines (representing completed journeys) * **Estimated partial leg** and **Estimated full legs**: Display as dashed lines (representing future predictions) 3. **Use the properties** to add interactivity: * Show port details (name, country, timestamps) on click/hover * Display vessel information (name, IMO, speed, heading) for the current vessel * Show leg information (departure/arrival times, vessel ID) for path segments ```javascript theme={null} // Fetch the GeoJSON data fetch('https://api.terminal49.com/v2/containers/{id}/map_geojson', { headers: { 'Authorization': 'Token YOUR_API_TOKEN' } }) .then(response => response.json()) .then(geojson => { // Create a map const map = L.map('map').setView([20, 70], 3); // Add base layer L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); // Process each feature geojson.features.forEach(feature => { const props = feature.properties; if (props.feature_type === 'port') { // Add port marker const marker = L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]]) .addTo(map) .bindPopup(`${props.label}
${props.name}`); } else if (props.feature_type === 'current_vessel') { // Add current vessel marker const vesselIcon = L.icon({ iconUrl: 'vessel-icon.png', iconSize: [32, 32] }); L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], {icon: vesselIcon}) .addTo(map) .bindPopup(`${props.vessel_name}
Speed: ${props.vessel_location_speed} knots`); } else if (props.feature_type === 'past_vessel_locations') { // Add past path as solid line const coordinates = feature.geometry.coordinates.map(coord => [coord[1], coord[0]]); L.polyline(coordinates, {color: 'green', weight: 3}) .addTo(map); } else if (props.feature_type === 'estimated_full_legs' || props.feature_type === 'estimated_partial_leg') { // Add estimated path as dashed line const coordinates = feature.geometry.coordinates.map(coord => [coord[1], coord[0]]); L.polyline(coordinates, {color: 'blue', weight: 2, dashArray: '10, 10'}) .addTo(map); } }); }); ```
## Use Cases Integrating Terminal49's Vessel and Container Route APIs enables a variety of advanced capabilities: * **Track Complete Shipment Journeys Visually:** Monitor shipments across multiple legs on a map, from the port of lading to the port of discharge, including all transshipment points. * **Identify Transshipment Details Geographically:** Clearly see where transshipments occur and the routes taken between them. * **Correlate Timestamps with Locations:** Visually connect ETDs, ETAs, ATDs, and ATAs for every leg with their geographical points on the map for precise planning and exception management. * **Improve Internal Logistics Dashboards:** Offer your operations team a clear visual overview of all ongoing shipments and their current locations. ## Recommendations and Best Practices * **Polling Intervals**: For active containers (currently at sea), we recommend refreshing the map data up to once per hour to get updated vessel positions. For containers that have completed their journey, you can cache the data as it won't change. * **Error Handling**: Implement proper error handling for API requests. If a container doesn't have route data yet, the endpoint will return an empty FeatureCollection (`{"type": "FeatureCollection", "features": []}`). If you decide to create your own map: * **Data Layering:** Consider layering information on your map. Start with basic port markers and paths, then add details like vessel names, ETAs, or status on hover or click. * **Map Library Integration:** Use a robust mapping library (e.g., Leaflet, Mapbox GL, Google Maps, OpenLayers) to handle the rendering of markers, lines, and map interactivity. * **Styling Guidelines**: * Use distinct colors/styles for different feature types (ports, current vessel, past paths, estimated paths) * Consider using dashed lines for estimated paths and solid lines for completed paths * Add labels to port markers showing POL, POD, TS1, etc. * Display vessel information in popups or info panels * **Data Interpretation**: * The `ports_sequence` property helps you understand the order of ports in the journey * Use `inbound_ata_at` and `outbound_atd_at` to determine which legs are completed * The presence of a `current_vessel` feature indicates the container is currently at sea * **Handling Antimeridian Crossings**: When container routes cross the International Date Line (antimeridian at Β±180Β° longitude), standard map projections can display routes incorrectly, showing lines that wrap around the entire globe. For mapping libraries that don't natively handle antimeridian crossings, the recommended approach is to: (1) detect and split crossing LineStrings into separate segments, and (2) render map features across multiple world views (standard, East, and West) as needed. Below are more details: * **Detection**: Identify LineString features (past vessel locations or estimated paths) that cross the antimeridian by checking if consecutive coordinates have a longitude difference greater than 180Β°. * **Single Crossing Solution**: When one antimeridian crossing is detected: * Split the route into two segments: features before the crossing (based on `ports_sequence`) are drawn in the standard world view * Features after the crossing are drawn in an extended world view (East or West, depending on crossing direction) * Split the crossing LineString into two separate lines: one ending at the antimeridian in the standard view, and one starting from the antimeridian in the extended view * **Multiple Crossings**: For routes with more than one antimeridian crossing (rare but possible), render all features across three world views (standard, East, and West) with duplicated features. Split all crossing lines to prevent lines from wrapping across the globe. * **No Crossings**: If no antimeridian crossings are detected, render all features in the standard world view without any special handling. ## Frequently Asked Questions **Q: How up-to-date is the vessel position data?** A: Vessel location data is updated every 15 minutes, although that does not guarantee there will be a new position every 15 minutes due to factors like whether the vessel is transmitting or within range of a satellite or base station. **Q: How accurate are the future predictions?** A: Predicted future positions are based on algorithms and historical data. Their accuracy can vary based on many factors such as temporary deviations, weather conditions, seasonality, or how frequently the shipping lane is used. **Q: What if a vessel deviates from the predicted path?** A: Predicted paths are estimates. The historical path (once available as a `past_vessel_locations` feature) will show the actual route taken. Regularly refreshing data for active shipments is key to getting the most accurate information. **Q: Why don't I see a `current_vessel` feature for my container?** A: The `current_vessel` feature is only present when: * The container is currently on a vessel at sea * The vessel has departed from a port (`outbound_atd_at` is present) * The next port hasn't been reached yet (`inbound_ata_at` is not present) * A valid vessel location can be retrieved **Q: Can I get map data for multiple containers at once?** A: Currently, the endpoint returns data for a single container. You'll need to make separate API calls for each container you want to display on your map. **Q: What coordinate system is used?** A: All coordinates follow the GeoJSON standard: `[longitude, latitude]` in WGS84 (EPSG:4326) format. **Q: Are the LineString coordinates simplified?** A: The endpoint applies simplification to reduce the number of points in LineStrings for better performance. The simplification tolerance can vary, but the paths remain accurate for visualization purposes. # Terminal49 Map Embed Guide Source: https://terminal49.com/docs/api-docs/in-depth-guides/terminal49-map The Terminal49 Map allows you to embed real-time visualized container tracking on your website with just a few lines of code. ### Prerequisites * A Terminal49 account. * A Publishable API key, you can get one by reaching out to us at [support@terminal49.com](mailto:support@terminal49.com). * Familiarity with our [Shipments API](/api-docs/api-reference/shipments/list-shipments) and [Containers API](/api-docs/api-reference/containers/list-containers). In the following examples we'll be passing a `containerId` and `shipmentId` variables to the embedded map. They relate to `id` attributes of the container and shipment objects that are returned by the API. ### How do I embed the map on my website? Once you have the API Key, you can embed the map on your website. 1. Copy and paste the code below and insert it on your website. Once loaded, this will make the map code available through the global `window` object. Just before the closing `` tag, add the following link tag to load the map styles. ```html theme={null} Document ``` Just before the closing `` tag, add the following script tag to load the map code. ```html theme={null} ``` 2. Define a container where you want the map to be displayed. ```html theme={null}
``` 3. After the code is loaded, you can use the `window.TntMap` class to create a map instance. ```javascript theme={null} const map = new window.TntMap("#map", { authToken: publishableApiKey, }); ``` Notice that the `authToken` option is required. This is where you pass your Publishable API key. 4. Start the map. This tells the map to initialize and hook into the element designated during initialization. ```javascript theme={null} await map.start(); ``` 5. Final step: load a container. You can pass shipment and container ids to the map where it'll fetch the data and display it. ```javascript theme={null} await map.load(shipmentId, containerId); ``` 6. Putting it all together, here is the javascript code that you need to embed the map on your website. ```javascript theme={null} const map = new window.TntMap("#map", { authToken: publishableApiKey, }); await map.start(); await map.load(shipmentId, containerId); ``` If you want to use inside the browser you can use the IIFE pattern. ```javascript theme={null} ``` Or you can use module attribute to use top-level async/await. ```javascript theme={null} ``` terminal49-map.png Additionally, the map element doesn't have to be an element id but can be a DOM element reference instead. Consider this example where we use a query selector to select the map element. ```javascript theme={null} const element = document.querySelector("#map"); const map = new window.TntMap(element, { authToken: publishableApiKey, }); ``` ### Styling the map All of the map styles are written as human-readable CSS classes and variables. You can used those to customize the map to your liking. The styles are written in [BEM](https://getbem.com/) style as well as they're scoped under a `.tntm` class to avoid style conflicts with your website. #### Sizing By default the map will take the full width of its container and some height. The map is expandable by clicking on the expand button on the bottom left corner of the map. You can also override the default styles to customize the map to your liking. Let's say you want to tell the map to take 60% of the total viewport size when expanded, we'd do this as follows: ```css theme={null} .tntm .tntm__container.--expanded { height: 60vh; } ``` terminal49-map-expanded.png #### Colors We expose a number of CSS variables that you can use to customize the map colors. All of the variables are bound to the `.tntm` class to avoid style conflicts with your website. ```css theme={null} .tntm { --marker-background-color: var(--athens-gray-500); --marker-border-color: var(--athens-gray-500); --marker-text-color: var(--white); --marker-secondary-background-color: var(--athens-gray-100); --marker-secondary-text-color: var(--athens-gray-500); } ``` By default their values are set to the Terminal49 brand colors, which we don't recommend changing and only focus on the `--marker` variants instead. Additionally the variables might require adjusting for different states of the map markers. What does that mean? Let's say we want to display markers 'visited' by a vessel as orange and the others - that we call are in 'on-the-way' state as blue. First let's define the default, blue color: ```css theme={null} .tntm [data-journey-state='on-the-way'] { --marker-background-color: blue; --marker-border-color: lightblue; --marker-text-color: var(--white); --marker-secondary-background-color: lightblue; --marker-secondary-text-color: black; } .tntm [data-journey-state='visited'] { --marker-background-color: orange; --marker-border-color: #FFD580; --marker-text-color: var(--white); --marker-secondary-background-color: #FFD580; --marker-secondary-text-color: black; } ``` Result: terminal49-map-colors.png It's also possible to change the marker colors based on wheter they're hovered over or not. This is what we do on the Terminal49 website to style the map markers to our needs: ```css theme={null} [data-journey-state='visited'] { --marker-background-color: var(--green-600); --marker-border-color: var(--green-600); --marker-text-color: var(--white); --marker-secondary-background-color: var(--green-50); --marker-secondary-text-color: var(--green-600); } [data-journey-state='on-the-way'] { --marker-background-color: var(--athens-gray-500); --marker-border-color: var(--athens-gray-500); --marker-text-color: var(--white); --marker-secondary-background-color: var(--athens-gray-100); --marker-secondary-text-color: var(--athens-gray-500); } [data-hovered][data-journey-state='visited'], [data-hovered] [data-journey-state='visited'] { --marker-secondary-background-color: var(--green-200); --marker-secondary-text-color: var(--green-700); --marker-border-color: var(--green-700); } [data-hovered][data-journey-state='on-the-way'], [data-hovered] [data-journey-state='on-the-way'] { --marker-secondary-background-color: var(--athens-gray-200); --marker-secondary-text-color: var(--athens-gray-600); --marker-border-color: var(--athens-gray-600); } ``` You might want to copy this code and adjust it to your needs. # Tracking Widget Embed Guide Source: https://terminal49.com/docs/api-docs/in-depth-guides/terminal49-widget The Terminal49 Track & Trace Widget allows you to embed real-time container tracking on your website with just a few lines of code. This widget provides a seamless user experience and helps improve customer satisfaction. ### How do I embed the widget on my website? > First, you neeed a publishable API KEY. You can get this by reaching out to us at [support@terminal49.com](mailto:support@terminal49.com) Once you have the key, you can embed the widget on your website. We suggest creating a dedicated page for tracking, typically at `company-website.com/track`. You can also embed the widget directly on your homepage. If you decide to create a dedicated tracking page, we recommend adding a `h1` tag above the script. Feel free to customize the `h1` contents in the script. Copy and pase the code below and insert it on top of the page (under your page navigation if you a horizontal top navigation). Replace `REPLACE_WITH_PUBLISHABLE_KEY` with the `API KEY` you receive from us. We suggest adding a `h1` tag above the script. Feel free to remove change the `h1` contents in the script below. To query a bill of lading, container, or reference number, simply replace `REPLACE_WITH_NUMBER_TO_QUERY` with the specific number you want to search for. If `data-number` exists, the query will be performed only once. ```html theme={null}

Tracking

``` ## Frequently Asked Questions ### How does it work? With a few lines of code, you can embed an interactive container tracking form. Once the widget is live on your website, your customer can enter a master bill of lading, container number, or reference numbers that a shipment is tagged with. After the number has been entered, the widget will retrieve and display shipment and container details from your Terminal49 account. ### Do I need Terminal49 account? Yes, the information that fetched and displayed by the widget is based on the shipments and containers tracked within your Terminal49 account. ### Can my customer track *any* shipment/container? No, only the shipments and containers that are tracked in your Terminal49 account. ### Is there a cost to embed the widget? Yes, there is a \$500/month fee to embed and use the widget. This include unlimited number of visitors and tracking requests. ## Terminal49 container tracking widget one-pager Here is a one-pager that describes the benefits of the Track & Trace Widget. Feel free to share it with your team or management if you want to demonstrate the benefits of adding track and trace functionality to your website. The Track & Trace Widget provides a number of advantages: * It offers your customers a convenient way to track their shipments and containers. * It helps to improve customer satisfaction by providing accurate container status. * It can reduce customer service costs by providing customers with the information they need without having to contact customer service. * It can help you differentiate from other service providers. terminal49-container-tracking-widget.jpg # Tracking Request Lifecycle Source: https://terminal49.com/docs/api-docs/in-depth-guides/tracking-request-lifecycle When you submit a tracking request your request is added to our queue to being checked at the shipping line. So what happens if the request doesn't go through correctly? If we are having difficulty connecting to the shipping line, or if we are unable to parse the response from the shipping line, we will keep retrying up to 14 times. This process can take up to approximately 24 hours. You will not receive a `tracking_request.failed` webhook notification until we have exhausted the retries, and the `status` field will not be changed to `failed` until then. ## Request Number Not Found / Awaiting Manifest If the shipping line returns a response that it cannot find the provided number we either immediately fail the tracking request or keep trying depending on whether the `request_type` is a container or not: * **Containers** fail straight away after a not found response from the shipping line. * **Bill of lading** and **booking numbers** do not fail instantly. We change the `status` to `awaiting_manifest` and will keep checking your request daily. You will receive a `tracking_request.awaiting_manifest` webhook notification the first time it happens. If your request number cannot be found after 7 days we will mark the tracking request as failed by changing the `status` field `failed` and sending the `tracking_request.failed` event to your webhook. * Should you wish to adjust the duration before marking your tracking requests as failed, please contact us throughΒ [support@terminal49.com](mailto:support@terminal49.com). * **Incorrect request number type** if the request number type (ex. booking number) is incorrect, the tracking request will still fail even though the request number is correct. To reduce tracking failures, use [Auto-Detect Carrier](/api-docs/in-depth-guides/auto-detect-carrier) to validate numbers and identify the correct SCAC before submitting. ## Failed Reason ### Temporary The `failed_reason` field can take one of the following temporary values: * `unrecognized_response` when we could not parse the response from the shipping line, * `shipping_line_unreachable` if the shipping line was unreachable, * `internal_processing_error` when we faced other issue, * `awaiting_manifest` if the shipping line indidicates a bill of lading number is found, but data is not yet available, or if the requested number could not be found. ### Permanent Temporary reasons can become permanent when the `status` changes to `failed`: * `duplicate` when the shipment already existed, * `expired` when the tracking request was created more than 7 days ago and still not succeded, * `retries_exhausted` if we tried for 14 times to no avail, * `not_found` if the shipping line could not find the BL number. * `invalid_number` if the shipping line rejects the formatting of the number. * `booking_cancelled` if the shipping line indicates that the booking has been cancelled. * `data_unavailable` if the number is valid but the shipping line will not provide the data. Examples include shipments that are flagged as private or results that are removed due to data retention policies. [Failed Reasons when tracking request through dashboard](https://help.terminal49.com/en/articles/6116676-what-happens-after-i-add-a-shipment-to-terminal49-recently-added-shipments#h_ac9b93504f) ## Stopped When a shipment is no longer being updated then the tracking request `status` is marked as `tracking_stopped`. You may subscribe to the event `tracking_request.tracking_stopped` for notifications when this occurs. Terminal49 will stop tracking requests for the following reasons: * The booking was cancelled. * The data is no longer available at the shipping line. * All shipment containers are marked `empty_returned`. * More than 56 days have passed since the shipment arrived at it's 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. ## Retrieving Status If you want to see the status of your tracking request you can make a [GET request](/api-docs/api-reference/tracking-requests/get-a-single-tracking-request) on what the most recent failure reason was (`failed_reason` field). # Webhooks Source: https://terminal49.com/docs/api-docs/in-depth-guides/webhooks ## Creating Webhooks You may subscribe to events through webhooks to be alerted when events are triggered. Visit [https://app.terminal49.com/developers/webhooks](https://app.terminal49.com/developers/webhooks) and click the 'Create Webhook Endpoint' button to create your webhook through the UI. If you prefer to create webhooks programatically then see the [webhooks post endpoint documentation](/api-docs/api-reference/webhooks/create-a-webhook). ## Available Webook Events Each `WebhookNotification` event represents some change to a model which you may be notified of. List of Supported Events: | Event | Description | | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | `tracking_request.succeeded` | Shipment created and linked to `TrackingRequest` | | `tracking_request.failed` | `TrackingRequest` failed and shipment was not created | | `tracking_request.awaiting_manifest` | `TrackingRequest` awaiting a manifest | | `tracking_request.tracking_stopped` | Terminal49 is no longer updating this `TrackingRequest`. | | `container.transport.empty_out` | Empty out at port of lading | | `container.transport.full_in` | Full in at port of lading | | `container.transport.vessel_loaded` | Vessel loaded at port of lading | | `container.transport.vessel_departed` | Vessel departed at port of lading | | `container.transport.transshipment_arrived` | Container arrived at transhipment port | | `container.transport.transshipment_discharged` | Container discharged at transhipment port | | `container.transport.transshipment_loaded` | Container loaded at transhipment port | | `container.transport.transshipment_departed` | Container departed at transhipment port | | `container.transport.feeder_arrived` | Container arrived on feeder vessel or barge | | `container.transport.feeder_discharged` | Container discharged from feeder vessel or barge | | `container.transport.feeder_loaded` | Container loaded on feeder vessel or barge | | `container.transport.feeder_departed` | Container departed on feeder vessel or barge | | `container.transport.vessel_arrived` | Container arrived on vessel at port of discharge (destination port) | | `container.transport.vessel_berthed` | Container on vessel berthed at port of discharge (destination port) | | `container.transport.vessel_discharged` | Container discharged at port of discharge | | `container.transport.full_out` | Full out at port of discharge | | `container.transport.empty_in` | Empty returned at destination | | `container.transport.rail_loaded` | Rail loaded | | `container.transport.rail_departed` | Rail departed | | `container.transport.rail_arrived` | Rail arrived | | `container.transport.rail_unloaded` | Rail unloaded | | `shipment.estimated.arrival` | ETA change notification (for port of discharge) | | `container.created` | Container added to shipment. Helpful for seeing new containers on a booking or BL. | | `container.updated` | Container attribute(s) updated (see below example) | | `container.pod_terminal_changed` | Port of discharge assignment changed for container | | `container.transport.arrived_at_inland_destination` | Container arrived at inland destination | | `container.transport.estimated.arrived_at_inland_destination` | ETA change notification (for destination) | | `container.pickup_lfd.changed` | Last Free Day (LFD) changed for container | | `container.pickup_lfd_line.changed` | Shipping Line Last Free Day (LFD) changed for container | | `container.transport.available` | Container is available at destination | ## Receiving Webhooks When an event is triggered we will attempt to post to the URL you provided with the webhook. The payload of every webhook is a `webhook_notification`. Each Webhook notification includes a `reference_object` in it's relationships which is the subject of that notification (e.g. a tracking request, or an updated container). Please note that we expect the endpoint to return [HTTP 200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200), [HTTP 201](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201), [HTTP 202](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202) or [HTTP 204](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204). We aim to deliver all webhook notifications, so any other response, including timeout, will result in a dozen of retries. ```json json_schema theme={null} { "type":"object", "properties":{ "data":{ "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "type": { "type": "string", "enum": [ "webhook_notification" ] }, "attributes": { "type": "object", "properties": { "event": { "type": "string" }, "delivery_status": { "type": "string", "default": "pending", "enum": [ "pending", "succeeded", "failed" ], "description": "Whether the notification has been delivered to the webhook endpoint" }, "created_at": { "type": "string" } }, "required": [ "event", "delivery_status", "created_at" ] }, "relationships": { "type": "object", "properties": { "webhook": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "type": { "type": "string", "enum": [ "webhook" ] } } } } }, "reference_object": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "type": { "type": "string", "enum": [ "tracking_request", "estimated_event", "transport_event", "container_updated_event" ] } } } } } }, "required": [ "webhook" ] } } }, "included":{ "type":"array", "items": { "anyOf": [ { "type": "object", "title": "Webhook", }, { "type": "object", "title": "Tracking Request", }, { "type": "object", "title": "Transport Event", }, { "type": "object", "title": "Estimated Event", }, { "type": "object", "title": "Container Updated Event", }, { "type": "object", "title": "Terminal", }, { "type": "object", "title": "Port", }, ] } } } } ``` > [How to Troubleshoot Missing Webhook Notifications](https://help.terminal49.com/en/articles/7851422-missing-webhook-notifications) ## Security There are a few ways you can verify the webhooks sent by Terminal49. Verify webhook signatures to confirm that received events are sent from Terminal49. Additionally, Terminal49 sends webhook events from a set list of IP addresses. Only trust events coming from these IP addresses. ### Webhook notification origin IP The full list of IP addresses that webhook notifications may come from is: ``` 35.222.62.171 3.230.67.145 44.217.15.129 ``` ### Verifying the webhook signature (optional) When you create or get a webhook the model will include an attribute `secret`. Whenever a webhook notification is delivered we create a signature by using the webhook `secret` as the key to generate a HMAC hex digest with SHA-256 on the body. This signature is added as the header `X-T49-Webhook-Signature` If you would like to verify that the webhook payload has not been tampered with by a 3rd party, then you can perform the same operation on the response body with the webhook secret and confirm that the digests match. Below is a basic example of how this might look in a rails application. ```ruby theme={null} class WebhooksController < ApplicationController def receive_tracking_request secret = ENV.fetch('TRACKING_REQUEST_WEBHOOK_SECRET') raise 'InvalidSignature' unless valid_signature?(request, secret) # continue processing webhook payload... end private def valid_signature?(request, secret) hmac = OpenSSL::HMAC.hexdigest('SHA256', secret, request.body.read) request.headers['X-T49-Webhook-Signature'] == hmac end end ``` ## Webhook Notification Examples ### container.updated The container updated event lets you know about changes to container properties at the terminal, or which terminal the container is (or will be) located at. The `changeset` attribute on is a hash of all the properties which changed on the container. Each changed property is the hash key. The prior value is the first item in the array, and the current value is the second item in the array. For example: ``` "changeset": { "pickup_lfd": [null, "2020-05-20 00:00:00"] } ``` Shows that the pickup last free day has changed from not being set to May 20 2020. The properties we show changes for are: * fees\_at\_pod\_terminal (see [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees)) * holds\_at\_pod\_terminal (see [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees)) * pickup\_lfd * pickup\_appointment\_at * available\_for\_pickup * pod\_terminal In every case the attribute `container_updated.timestamp` tells you when we picked up the changes from the terminal. As container availability becomes known or changes at the POD Terminal we will send `container_updated` events with the key `available_for_pickup` in the `changeset`. ```json theme={null} { "data": { "id": "fa1a6731-4b34-4b0c-aabc-460892055ba1", "type": "webhook_notification", "attributes": { "id": "fa1a6731-4b34-4b0c-aabc-460892055ba1", "event": "container.updated", "delivery_status": "pending", "created_at": "2023-01-24T00:11:32Z" }, "relationships": { "reference_object": { "data": { "id": "e8f1976c-0089-4b98-96ae-90aa87fbdfee", "type": "container_updated_event" } }, "webhook": { "data": { "id": "8a5ffa8f-3dc1-48de-a0ea-09fc4f2cd96f", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "adc08630-51d3-4bbc-a859-5157cbbe806c", "type": "shipment", "attributes": { "created_at": "2023-01-24T00:11:32Z", "ref_numbers": [ "REF-50FFA3", "REF-5AC291" ], "tags": [ ], "bill_of_lading_number": "TE49DD306F13", "normalized_number": "TE49DD306F13", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2023-01-11T00:11:32Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2023-01-23T20:11:32Z", "pod_ata_at": "2023-01-23T23:11:32Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": "2023-01-24T00:11:32Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "588711e2-3f78-4178-ae5e-ccb690e0671d", "type": "port" } }, "port_of_discharge": { "data": { "id": "9a25e0aa-52bd-4bb8-8876-cd7616f5fb0f", "type": "port" } }, "pod_terminal": { "data": { "id": "4960e227-93b1-4f85-bf7c-07c9b6f597e0", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "26d8be45-b428-45fa-819b-46c828bf6fac", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "3cd51f0e-eb18-4399-9f90-4c8a22250f63", "type": "container" } ] } }, "links": { "self": "/v2/shipments/adc08630-51d3-4bbc-a859-5157cbbe806c" } }, { "id": "9a25e0aa-52bd-4bb8-8876-cd7616f5fb0f", "type": "port", "attributes": { "id": "9a25e0aa-52bd-4bb8-8876-cd7616f5fb0f", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "time_zone": "America/Los_Angeles" } }, { "id": "4960e227-93b1-4f85-bf7c-07c9b6f597e0", "type": "terminal", "attributes": { "id": "4960e227-93b1-4f85-bf7c-07c9b6f597e0", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985" }, "relationships": { "port": { "data": { "id": "9a25e0aa-52bd-4bb8-8876-cd7616f5fb0f", "type": "port" } } } }, { "id": "3cd51f0e-eb18-4399-9f90-4c8a22250f63", "type": "container", "attributes": { "number": "COSU1186800", "seal_number": "43e29239e5dd5276", "created_at": "2023-01-24T00:11:32Z", "ref_numbers": [ "REF-C86614", "REF-456CEA" ], "pod_arrived_at": "2023-01-23T23:11:32Z", "pod_discharged_at": "2023-01-24T00:11:32Z", "final_destination_full_out_at": null, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 43333, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "holds_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "availability_known": true, "available_for_pickup": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "adc08630-51d3-4bbc-a859-5157cbbe806c", "type": "shipment" } }, "pod_terminal": { "data": { "id": "4960e227-93b1-4f85-bf7c-07c9b6f597e0", "type": "terminal" } }, "transport_events": { "data": [ ] }, "raw_events": { "data": [ ] } } }, { "id": "e8f1976c-0089-4b98-96ae-90aa87fbdfee", "type": "container_updated_event", "attributes": { "changeset": { "available_for_pickup": [ false, true ] }, "timestamp": "2023-01-24T00:11:32Z", "data_source": "terminal", "timezone": "America/Los_Angeles" }, "relationships": { "container": { "data": { "id": "3cd51f0e-eb18-4399-9f90-4c8a22250f63", "type": "container" } }, "terminal": { "data": { "id": "4960e227-93b1-4f85-bf7c-07c9b6f597e0", "type": "terminal" } }, "shipment": { "data": { "id": "adc08630-51d3-4bbc-a859-5157cbbe806c", "type": "shipment" } } } } ] } ``` The `pod_terminal` is a relationship of the container. When the pod\_terminal changes the id is included. The terminal will be serialized in the included models. N.B. the `container_updated_event` also has a relationship to a `terminal` which refers to where the information came from. Currently this is always the POD terminal. In the future this may be the final destination terminal or an off-dock location. ```json theme={null} { "data": { "id": "f6c5e340-94bf-4681-a47d-f2e8d6c90e59", "type": "webhook_notification", "attributes": { "id": "f6c5e340-94bf-4681-a47d-f2e8d6c90e59", "event": "container.updated", "delivery_status": "pending", "created_at": "2023-01-24T00:13:06Z" }, "relationships": { "reference_object": { "data": { "id": "567eccef-53bf-43d5-b3d8-00278d7710df", "type": "container_updated_event" } }, "webhook": { "data": { "id": "2e5f41d1-8a3b-4940-a9bb-ff0481e09c71", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "c74ff2a5-5ede-4fc2-886b-3eeef886ff32", "type": "shipment", "attributes": { "created_at": "2023-01-24T00:13:05Z", "ref_numbers": [ "REF-29557A" ], "tags": [ ], "bill_of_lading_number": "TE497F86D5B7", "normalized_number": "TE497F86D5B7", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2023-01-11T00:13:05Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2023-01-23T21:13:05Z", "pod_ata_at": "2023-01-24T00:13:05Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": "2023-01-24T00:13:05Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "8d0f0cba-9961-4fa5-9bf0-0fb5fb67bdbe", "type": "port" } }, "port_of_discharge": { "data": { "id": "9722a830-634e-4f7a-b1b3-793ccaf8cbb2", "type": "port" } }, "pod_terminal": { "data": { "id": "08831e36-766b-4ac8-8235-d8594b55ff6d", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "f2a6a6e2-4bd1-4c66-aa8b-be4cb2ddc9a8", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "adf4673d-f4ba-41a9-82da-55c0ae3b3722", "type": "container" } ] } }, "links": { "self": "/v2/shipments/c74ff2a5-5ede-4fc2-886b-3eeef886ff32" } }, { "id": "9722a830-634e-4f7a-b1b3-793ccaf8cbb2", "type": "port", "attributes": { "id": "9722a830-634e-4f7a-b1b3-793ccaf8cbb2", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "time_zone": "America/Los_Angeles" } }, { "id": "08831e36-766b-4ac8-8235-d8594b55ff6d", "type": "terminal", "attributes": { "id": "08831e36-766b-4ac8-8235-d8594b55ff6d", "nickname": "STO", "name": "Shippers Transport Express", "firms_code": "STO" }, "relationships": { "port": { "data": { "id": "9722a830-634e-4f7a-b1b3-793ccaf8cbb2", "type": "port" } } } }, { "id": "adf4673d-f4ba-41a9-82da-55c0ae3b3722", "type": "container", "attributes": { "number": "CGMU1560506", "seal_number": "a9948b719482648c", "created_at": "2023-01-24T00:13:06Z", "ref_numbers": [ "REF-D2AC6F", "REF-34E84B" ], "pod_arrived_at": "2023-01-24T00:13:05Z", "pod_discharged_at": "2023-01-24T00:13:05Z", "final_destination_full_out_at": null, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 43481, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "holds_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "availability_known": true, "available_for_pickup": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "c74ff2a5-5ede-4fc2-886b-3eeef886ff32", "type": "shipment" } }, "pod_terminal": { "data": { "id": "08831e36-766b-4ac8-8235-d8594b55ff6d", "type": "terminal" } }, "transport_events": { "data": [ ] }, "raw_events": { "data": [ ] } } }, { "id": "0ef5519f-1b39-4f6c-9961-1bbba0ac1307", "type": "terminal", "attributes": { "id": "0ef5519f-1b39-4f6c-9961-1bbba0ac1307", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985" }, "relationships": { "port": { "data": { "id": "9722a830-634e-4f7a-b1b3-793ccaf8cbb2", "type": "port" } } } }, { "id": "567eccef-53bf-43d5-b3d8-00278d7710df", "type": "container_updated_event", "attributes": { "changeset": { "pod_terminal": [ "0ef5519f-1b39-4f6c-9961-1bbba0ac1307", "08831e36-766b-4ac8-8235-d8594b55ff6d" ] }, "timestamp": "2023-01-24T00:13:06Z", "data_source": "terminal", "timezone": "America/Los_Angeles" }, "relationships": { "container": { "data": { "id": "adf4673d-f4ba-41a9-82da-55c0ae3b3722", "type": "container" } }, "terminal": { "data": { "id": "0ef5519f-1b39-4f6c-9961-1bbba0ac1307", "type": "terminal" } }, "shipment": { "data": { "id": "c74ff2a5-5ede-4fc2-886b-3eeef886ff32", "type": "shipment" } } } } ] } ``` ### tracking\_request.succeeded ```json theme={null} { "data": { "id": "a76187fc-5749-43f9-9053-cfaad9790a31", "type": "webhook_notification", "attributes": { "id": "a76187fc-5749-43f9-9053-cfaad9790a31", "event": "tracking_request.succeeded", "delivery_status": "pending", "created_at": "2020-09-11T21:25:34Z" }, "relationships": { "reference_object": { "data": { "id": "bdeca506-9741-4ab1-a0a7-cfd1d908e923", "type": "tracking_request" } }, "webhook": { "data": { "id": "914b21ce-dd7d-4c49-8503-65aba488e9a9", "type": "webhook" } }, "webhook_notification_logs": { "data": [] } } }, "included": [ { "id": "bdeca506-9741-4ab1-a0a7-cfd1d908e923", "type": "tracking_request", "attributes": { "request_number": "TE497ED1063E", "request_type": "bill_of_lading", "scac": "MSCU", "ref_numbers": [], "created_at": "2020-09-11T21:25:34Z", "updated_at": "2020-09-11T22:25:34Z", "status": "created", "failed_reason": null, "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": { "id": "b5b10c0a-8d18-46da-b4c2-4e5fa790e7da", "type": "shipment" } } }, "links": { "self": "/v2/tracking_requests/bdeca506-9741-4ab1-a0a7-cfd1d908e923" } }, { "id": "b5b10c0a-8d18-46da-b4c2-4e5fa790e7da", "type": "shipment", "attributes": { "created_at": "2020-09-11T21:25:33Z", "bill_of_lading_number": "TE497ED1063E", "ref_numbers": [], "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2020-08-29T21:25:33Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2020-09-18T21:25:33Z", "pod_ata_at": null, "pod_timezone": "America/Los_Angeles" }, "relationships": { "port_of_lading": { "data": { "id": "4384d6a5-5ccc-43b7-8d19-4a9525e74c08", "type": "port" } }, "port_of_discharge": { "data": { "id": "2a765fdd-c479-4345-b71d-c4ef839952e2", "type": "port" } }, "pod_terminal": { "data": { "id": "17891bc8-52da-40bf-8ff0-0247ec05faf1", "type": "terminal" } }, "destination": { "data": null }, "containers": { "data": [ { "id": "b2fc728c-e2f5-4a99-8899-eb7b34ef22d7", "type": "container" } ] } }, "links": { "self": "/v2/shipments/b5b10c0a-8d18-46da-b4c2-4e5fa790e7da" } }, { "id": "b2fc728c-e2f5-4a99-8899-eb7b34ef22d7", "type": "container", "attributes": { "number": "ARDU1824900", "seal_number": "139F1451", "created_at": "2020-09-11T21:25:34Z", "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 53507, "fees_at_pod_terminal": [], "holds_at_pod_terminal": [], "pickup_lfd": null, "pickup_appointment_at": null, "availability_known": true, "available_for_pickup": false, "pod_arrived_at": null, "pod_discharged_at": null, "location_at_pod_terminal": null, "final_destination_full_out_at": null, "pod_full_out_at": null, "empty_terminated_at": null }, "relationships": { "shipment": { "data": { "id": "b5b10c0a-8d18-46da-b4c2-4e5fa790e7da", "type": "shipment" } }, "pod_terminal": { "data": { "id": "17891bc8-52da-40bf-8ff0-0247ec05faf1", "type": "terminal" } }, "transport_events": { "data": [ { "id": "56078596-5293-4c84-9245-cca00a787265", "type": "transport_event" } ] } } }, { "id": "56078596-5293-4c84-9245-cca00a787265", "type": "transport_event", "attributes": { "event": "container.transport.vessel_departed", "created_at": "2020-09-11T21:25:34Z", "voyage_number": null, "timestamp": "2020-08-29T21:25:33Z", "location_locode": "MXZLO", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "b5b10c0a-8d18-46da-b4c2-4e5fa790e7da", "type": "shipment" } }, "container": { "data": { "id": "b2fc728c-e2f5-4a99-8899-eb7b34ef22d7", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "2a765fdd-c479-4345-b71d-c4ef839952e2", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ### shipment.estimated.arrival ```json theme={null} { "data": { "id": "b03bcf3c-252d-41f8-b86f-939b404e304b", "type": "webhook_notification", "attributes": { "id": "b03bcf3c-252d-41f8-b86f-939b404e304b", "event": "shipment.estimated.arrival", "delivery_status": "pending", "created_at": "2022-01-13T19:56:58Z" }, "relationships": { "reference_object": { "data": { "id": "14b5047f-e3e7-4df7-a570-2d3878e6d863", "type": "estimated_event" } }, "webhook": { "data": { "id": "d60a23a4-f40d-44d2-8b6a-2e55a527e6a2", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "14b5047f-e3e7-4df7-a570-2d3878e6d863", "type": "estimated_event", "attributes": { "created_at": "2022-01-13T19:56:58Z", "estimated_timestamp": "2022-01-16T19:56:58Z", "voyage_number": "098N", "event": "shipment.estimated.arrival", "location_locode": "USOAK", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "8e4a1f1e-aa13-4cad-9df0-aec6c791a5f8", "type": "shipment" } }, "port": { "data": { "id": "3ee88ea1-3b8b-4b96-80fb-6aa23ba7065e", "type": "port" } }, "vessel": { "data": { "id": "b1550abc-4e73-4271-a0f4-8ac031f242cd", "type": "vessel" } } } }, { "id": "3ee88ea1-3b8b-4b96-80fb-6aa23ba7065e", "type": "port", "attributes": { "id": "3ee88ea1-3b8b-4b96-80fb-6aa23ba7065e", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "time_zone": "America/Los_Angeles" } }, { "id": "8e4a1f1e-aa13-4cad-9df0-aec6c791a5f8", "type": "shipment", "attributes": { "created_at": "2022-01-13T19:56:58Z", "ref_numbers": [ "REF-3AA505", "REF-910757", "REF-2A8357" ], "tags": [ ], "bill_of_lading_number": "TE49C31E16E2", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2021-12-31T19:56:58Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2022-01-16T19:56:58Z", "pod_ata_at": null, "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": "2022-01-13T19:56:58Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "78ad2915-700b-4919-8ede-a3b6c2137436", "type": "port" } }, "port_of_discharge": { "data": { "id": "3ee88ea1-3b8b-4b96-80fb-6aa23ba7065e", "type": "port" } }, "pod_terminal": { "data": { "id": "3bd88777-48ea-4880-9cb9-961dd4d26a00", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "1d016b3d-96d5-4867-8f99-77233d1cc57d", "type": "terminal" } }, "containers": { "data": [ ] } }, "links": { "self": "/v2/shipments/8e4a1f1e-aa13-4cad-9df0-aec6c791a5f8" } } ] } ``` ### container.transport.vessel\_arrived ```json theme={null} { "data": { "id": "72f8b0b5-28f5-4a12-8274-71d4d23c9ab7", "type": "webhook_notification", "attributes": { "id": "72f8b0b5-28f5-4a12-8274-71d4d23c9ab7", "event": "container.transport.vessel_arrived", "delivery_status": "pending", "created_at": "2023-01-24T00:14:28Z" }, "relationships": { "reference_object": { "data": { "id": "c1443820-304a-444b-bf42-c3d885dc8daa", "type": "transport_event" } }, "webhook": { "data": { "id": "655236f8-7936-4611-b580-341d3e1103f5", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "290a696b-5fba-45aa-a08c-0e15ae89e9c0", "type": "shipment", "attributes": { "created_at": "2023-01-24T00:14:28Z", "ref_numbers": [ "REF-134938", "REF-BE2704", "REF-712D47" ], "tags": [ ], "bill_of_lading_number": "TE49735F4B1D", "normalized_number": "TE49735F4B1D", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2023-01-11T00:14:28Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2023-01-31T00:14:28Z", "pod_ata_at": "2023-01-31T01:14:28Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": "2023-01-24T00:14:28Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "036084b7-f2cc-49b5-9d81-7de2cdabfc69", "type": "port" } }, "port_of_discharge": { "data": { "id": "0e0c9ad6-ec83-48b3-87f9-c2710659821b", "type": "port" } }, "pod_terminal": { "data": { "id": "1ee2022a-e054-4f76-8c1a-60967e76b407", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "b07e8193-47cf-4395-a1f6-a5d4d7fa9b17", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "c8fa5c2a-1bd0-48d8-8c94-2ef8a06c4ce9", "type": "container" } ] } }, "links": { "self": "/v2/shipments/290a696b-5fba-45aa-a08c-0e15ae89e9c0" } }, { "id": "c8fa5c2a-1bd0-48d8-8c94-2ef8a06c4ce9", "type": "container", "attributes": { "number": "GLDU1222600", "seal_number": "d5103634ed1adbd4", "created_at": "2023-01-24T00:14:28Z", "ref_numbers": [ "REF-889564" ], "pod_arrived_at": "2023-01-24T00:14:28Z", "pod_discharged_at": "2023-01-24T00:14:28Z", "final_destination_full_out_at": "2023-01-24T00:14:28Z", "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 46679, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "holds_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "availability_known": true, "available_for_pickup": false, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "290a696b-5fba-45aa-a08c-0e15ae89e9c0", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "c1443820-304a-444b-bf42-c3d885dc8daa", "type": "transport_event" } ] }, "raw_events": { "data": [ ] } } }, { "id": "0e0c9ad6-ec83-48b3-87f9-c2710659821b", "type": "port", "attributes": { "id": "0e0c9ad6-ec83-48b3-87f9-c2710659821b", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "time_zone": "America/Los_Angeles" } }, { "id": "1ee2022a-e054-4f76-8c1a-60967e76b407", "type": "terminal", "attributes": { "id": "1ee2022a-e054-4f76-8c1a-60967e76b407", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985" }, "relationships": { "port": { "data": { "id": "0e0c9ad6-ec83-48b3-87f9-c2710659821b", "type": "port" } } } }, { "id": "100c303e-79df-4301-9bf7-13f9e0c85851", "type": "vessel", "attributes": { "name": "MSC CHANNE", "imo": "9710438", "mmsi": "255805864", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "c1443820-304a-444b-bf42-c3d885dc8daa", "type": "transport_event", "attributes": { "event": "container.transport.vessel_arrived", "created_at": "2023-01-24T00:14:27Z", "voyage_number": null, "timestamp": "2023-01-24T00:14:27Z", "data_source": "shipping_line", "location_locode": "USOAK", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "290a696b-5fba-45aa-a08c-0e15ae89e9c0", "type": "shipment" } }, "container": { "data": { "id": "c8fa5c2a-1bd0-48d8-8c94-2ef8a06c4ce9", "type": "container" } }, "vessel": { "data": { "id": "100c303e-79df-4301-9bf7-13f9e0c85851", "type": "vessel" } }, "location": { "data": { "id": "0e0c9ad6-ec83-48b3-87f9-c2710659821b", "type": "port" } }, "terminal": { "data": { "id": "1ee2022a-e054-4f76-8c1a-60967e76b407", "type": "terminal" } } } } ] } ``` # API Data Sources and Availability. Source: https://terminal49.com/docs/api-docs/useful-info/api-data-sources-availability Our platform gets data from variety of sources in order to create a complete view of a shipment and containers. However,some data is not universally available from all sources, and some data does not become available until certain milestones pass. This page will help you understand which data sources we support, and which data items should be universally expected by your code and which you need to code more defensively around. # Data Sources * **Ocean carriers (aka steamship lines):** bill of lading/booking details, vessel eta, containers and milestones * **Container terminal operators:** container availability, last free day, holds, fees etc * **Container rail carriers:** container milestones via rail * **AIS data:** vessel details and real-time location tracking (coming soon!) ## Supported Ocean Carriers View a complete list of supported carriers and attributes on [Google Sheets](https://docs.google.com/spreadsheets/d/1cWK8sNpkjY5V-KlXe1fHi8mU_at2HcJYqjCvGQgixQk/edit#gid=0) You can also use the [Auto-Detect Carrier](/api-docs/in-depth-guides/auto-detect-carrier) API to automatically identify the SCAC from a tracking number. [Carriers Screenshot](https://docs.google.com/spreadsheets/d/1cWK8sNpkjY5V-KlXe1fHi8mU_at2HcJYqjCvGQgixQk/edit#gid=0) ## Ports and Terminals Presently, the Terminal 49 api integrates with terminals at the following ports: * Baltimore * Boston * Charleston * Fraser Surrey (CA) * Halifax (CA) * Houston * Jacksonville * London Gateway (UK) * Long Beach * Los Angeles * Miami * Mobile * New Orleans * New York / New Jersey * Oakland * Philadelphia * Port Everglades * Portland * Prince Rupert (CA) * Savannah * Seattle * Southampton (UK) * Tacoma * Tampa * Vancouver (CA) * Virginia You can view a complete list of supported terminals and attributes on [Google Sheets](https://docs.google.com/spreadsheets/d/1cWK8sNpkjY5V-KlXe1fHi8mU_at2HcJYqjCvGQgixQk/edit#gid=1406366493) ## Rail Carriers * BNSF Railway * Canadian National Railway (CN) * Canadian Pacific Railway (CP) * CSX Transportation * Norfolk Southern Railway (NS) * Union Pacific Railroad (UP) ## Known Issues (ocean) Shipment data is populated from requests to the shipping lines. Below are a list of known issues with our data sources: ### Cma-Cgm, APL, ANL * No container weight * No container seal number ### Maersk, Sealand, Safmarine * Shipment departure/arrival events are not always available depending on when BL is entered into system. * No container seal number ### Hamburg SΓΌd * No estimated departure time * No container weight * No container seal number ### MSC * No container seal number ### Hapag Lloyd * No container weight * No container seal number ### Evergreen * All dates are provided as dates, not datetimes. We record and return them all as midnight at the location the event happened (when location is available) or midnight UTC. * Only Dry, Reefer, and Flatpack container types are mapped to our system ### COSCO * No departure or arrival events. Does not affect departure/arrival times. ### OOCL * No container seal number ### ONE * Only Dry, and Reefer container types are mapped to our system ### Yang-Ming * When BL has multiple containers, the container weight returned is the average of the shipment. (i.e. the BL gross weight / number of containers) ### Hyundai Merchant Marine * No container type ### ZIM * No container weight * No container seal number ### Westwood Shipping * No container weight * Only Dry container types are mapped to our system # Data Fields & Availability Below is a list of data that can be retrieved via the API, including whether is is always available, or whether it is only supported by certain carriers (Carrier Dependent), certain Terminals (Terminal Dependent) or on certain types of journeys (Journey dependent). ## Shipment Data Shipment Data is the primary data that comes from the Carrier. It containers the details of the shipment retrieved from the Bill of Lading, and references multiple container objects. | Data | Availability | More details | Notes | | ---------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | | Port of Lading | Always | Port of Lading name, Port of Lading UN/LOCODE, Port of Lading Timezone | | | Port of Discharge | Always | Port of Discharge name, Port of discharge UN/LOCODE,Port of Discharge Timezone | | | Final Destination beyond Port of Discharge | Carrier dependent, Journey Dependent | Destination name, Destination UN/LOCODE, Destination UN/LOCODE, Destination Timezone | Only for shipments with inland moves provided by or booked by the carrier. | | Listing of Container Numbers | Always | A list of container numbers with data attributes listed below | | | Bill of Lading Number | Always (inputted by user) | BOL | | | Shipping Line Details | Always | SCAC, SSL Name | | | Voyage Details | Milestone-based | Vessel Name, Vessel IMO, Voyage Number | | | Estimated Time of Departure | Carrier dependent | Timestamp | | | Actual Time of Departure | Always | Timestamp | After departure | | Estimated Time of Arrival at Port of Discharge | Carrier dependent | Timestamp | | | Actual Time of Arrival at Port of Discharge | Always | Timestamp | Available after arrival | | Estimated Time of Arrival at Final Destination | Carrier dependent, Journey dependent | Timestamp | Only for vessels with inland moves. | ## Container Data At the container level, the following data is available. Container data is combined from all sources to create a single data view of the container. As such some of this data will only available when certain milestones have passed. | Data | Availability | More Details | Notes | | -------------------------------------- | ------------------------------------ | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | | Container Number | Always | number | | | Seal Number | Carrier dependent | number | | | Equipment Type | Always | Dry, reefer, open top, flat rack, tank, hard top | Enumerated data type | | Equipment length | Always | 20, 40, 45, 50 | Enumerated Data Type | | Equipment height | Always | Standard, high cube | Enumerated Data Type | | Weight | Carrier Dependent | Number | | | Terminal Availability | Always | Availability Known, Availability for Pickup | | | Holds | Terminal Dependent | Array of statuses | Each status includes the hold name (one of: customs, freight, TMF, other, USDA) and the status (pending, hold) as well as any extra description | | Fees | Terminal Dependent | Array of statuses | Each status includes the fee type (one of: Demurrage, Exam, Other) and the amount the hold is for (a float) | | Last Free Day | Terminal Dependent | Date of last free day | | | Arrived at Port of Discharge | Always | Once Arrived | | | Discharged at Port of Discharge | Always | Once discharged | | | Full Out at Port of Discharge | Always | | | | Full out at final destination | Journey Dependent | Only if non-port final destination | | | Rail Loaded At Port of Discharge | Journey Dependent | Only if non-port final destination | | | Rail Departed At Port of Discharge | Journey Dependent | Only if non-port final destination | | | Rail Carrier Scac at Port of Discharge | Journey Dependent | Only if non-port final destination | | | ETA for final destination | Carrier Dependent, Journey Dependent | Only if non-port final destination | | | ATA for final destination | Journey Dependent | Only if non-port final destination | | | LFD at final destination | Carrier Dependent, Journey Dependent | Only if non-port final destination | | ## Milestone Event Data When a milestone passes, the Terminal49 API will ping one of your webhooks with a Milestone event. For each milestone, the following data is always provided. Container, Shipment, Vessel, Location and Terminal data will be provided as objects that contain the information listed above. | Milestone Data | Description | | -------------- | ---------------------------------------------------------------- | | Event Name | the name of the event. e.g. 'container.transport.vessel\_loaded' | | Created At | when the event was created in our system | | Timestamp | when the event occured | | Timezone | Which timezone did the event occur in. | | Voyage Number | the voyage number of the vessel | | Container | A link to the Container Data | | Shipment | A link to the Shipment Data | | Vessel | Which vessel did the event occur on. | | Location | Where did the event oocur. | | Terminal | Which terminal did this occur at. | ## Milestones Events Supported A list of milestones that the API can track, as well as the event name used in the API. In future, further events may be supported. | Milestone Event Name | Event Name | | --------------------------------------- | -------------------------------------------------------------- | | Vessel Loaded | container.transport.vessel\_loaded | | Vessel Departed | container.transport.vessel\_departed | | Vessel Arrived | container.transport.vessel\_arrived | | Vessel Berthed | container.transport.vessel\_berthed | | Vessel Discharged | container.transport.vessel\_discharged | | Empty Out | container.transport.empty\_out | | Full In | container.transport.full\_in | | Full Out | container.transport.full\_out | | Empty In | container.transport.empty\_in | | Rail Departed | container.transport.rail\_departed | | Rail Arrived | container.transport.rail\_arrived | | Rail Loaded | container.transport.rail\_loaded | | Rail Unloaded | container.transport.rail\_unloaded | | Transshipment Arrived | container.transport.transshipment\_arrived | | Transshipment Discharged | container.transport.transshipment\_discharged | | Transshipment Loaded | container.transport.transshipment\_loaded | | Transshipment Departed | container.transport.transshipment\_departed | | Feeder Arrived | container.transport.feeder\_arrived | | Feeder Discharged | container.transport.feeder\_discharged | | Feeder Loaded | container.transport.feeder\_loaded | | Feeder Departed | container.transport.feeder\_departed | | Arrived at inland destination | container.transport.arrived\_at\_inland\_destination | | Estimated Arrived at inland destination | container.transport.estimated.arrived\_at\_inland\_destination | | Pickup LFD changed | container.pickup\_lfd.changed | | Available at Destination | container.transport.available | # Pricing Source: https://terminal49.com/docs/api-docs/useful-info/pricing View our [standard API pricing on our website](https://www.terminal49.com/pricing-plans#API-Section) # Test Numbers Source: https://terminal49.com/docs/api-docs/useful-info/test-numbers ## Overview This page includes test `shipment` numbers and other information that you can use to make sure your integration works as planned. Use it to trigger different flows in your integration and ensure they are handled accordingly. ## What are test numbers? We have created a variety of test numbers that you can use to make calls the Tracking Request API and create fake shipments. Each number has a specific purpose and alows you to test and integrate specific flows. You can create tests against these numbers and always execpt to receive the same response. This is helpful when you want to test a specific webhooks notifications (ie: `shipment.eta_changed`, `shipment.vessel_arrived` etc) and you dont have a list of live shipments and containers that are in specific leg of their journey. ## Tracking Request API Shipments are created by making requests to the Tracking Request API. When using the API , ensure that: * you set the test number in `request_number` attribute in the request body * you set `scac` attribute as 'TEST' in the request body ## Test Numbers | Number. | Use Case | | ----------------- | ----------------------------------------- | | TEST-TR-SUCCEEDED | test `tracking_request.succeeded` webhook | | TEST-TR-FAILED | test `tracking_request.failed` webhook | # Tracking Request Retrying Source: https://terminal49.com/docs/api-docs/useful-info/tracking-request-retrying When you submit a tracking request your request is added to our queue to being checked at the shipping line. So what happens if the request doesn't go through correctly? If we are having difficulty connecting to the shipping line, or if we are unable to parse the response from the shipping line, we will keep retrying up to 14 times with an exponential back off. This process can take up to approximately 24 hours. You will not receive a `tracking_request.failed` webhook notification until we have exhausted the retries. If the shipping line returns a response that it cannot find the provided number then we will immediately return the `tracking_request.failed` event to your webhook. If you want to see the status of your tracking request you can make a [GET request](/api-docs/api-reference/tracking-requests/get-a-single-tracking-request) on it's `id` to see how many times it has retried, and what the most recent failure reason was. # Webhook Events Examples Source: https://terminal49.com/docs/api-docs/useful-info/webhook-events-examples Container payloads in these examples include `holds_at_pod_terminal`, `fees_at_pod_terminal`, and `available_for_pickup` fields. To understand the possible values and how to use them for pickup readiness, see [Container Holds, Fees, and Release Readiness](/api-docs/in-depth-guides/holds-and-fees). ## container.created ```json theme={null} { "data": { "id": "c6e6af71-f75d-49e3-9e79-50b719d8376e", "type": "webhook_notification", "attributes": { "id": "c6e6af71-f75d-49e3-9e79-50b719d8376e", "event": "container.created", "delivery_status": "succeeded", "created_at": "2022-10-21T20:18:43Z" }, "relationships": { "reference_object": { "data": { "id": "8d86b03a-0ff7-4efe-b893-4feaf7d0bddc", "type": "container_created_event" } }, "webhook": { "data": { "id": "f1c5487c-ac3c-4ddc-ad77-5d1f32f75669", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "0b315c62-71f2-4c04-b252-88096d7f226f", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:18:36Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "MAEU221876618", "normalized_number": "221876618", "shipping_line_scac": "MAEU", "shipping_line_name": "Maersk", "shipping_line_short_name": "Maersk", "customer_name": "Nienow LLC", "port_of_lading_locode": "CNNGB", "port_of_lading_name": "Ningbo", "port_of_discharge_locode": null, "port_of_discharge_name": null, "pod_vessel_name": null, "pod_vessel_imo": null, "pod_voyage_number": null, "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": null, "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-11-25T08:00:00Z", "pod_original_eta_at": "2022-11-25T08:00:00Z", "pod_ata_at": null, "pod_timezone": null, "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "9b8a6dcc-2f14-4d2d-a91b-5a154ee6fbf8", "type": "port" } }, "port_of_discharge": { "data": null }, "pod_terminal": { "data": null }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "ede7ebb0-19e6-4bad-afcd-824bb8ca3cd7", "type": "container" } ] } }, "links": { "self": "/v2/shipments/e5a39855-f438-467a-9c18-ae91cd46cfaf" } }, { "id": "ede7ebb0-19e6-4bad-afcd-824bb8ca3cd7", "type": "container", "attributes": { "number": "MRKU3700927", "seal_number": null, "created_at": "2022-10-21T20:18:36Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": null, "final_destination_timezone": null, "empty_terminated_timezone": null }, "relationships": { "shipment": { "data": { "id": "0b315c62-71f2-4c04-b252-88096d7f226f", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ ] }, "raw_events": { "data": [ ] } } }, { "id": "8d86b03a-0ff7-4efe-b893-4feaf7d0bddc", "type": "container_created_event", "attributes": { "timestamp": "2022-10-21T20:18:36Z", "timezone": "Etc/UTC" }, "relationships": { "container": { "data": { "id": "ede7ebb0-19e6-4bad-afcd-824bb8ca3cd7", "type": "container" } }, "shipment": { "data": { "id": "0b315c62-71f2-4c04-b252-88096d7f226f", "type": "shipment" } } } } ] } ``` ## container.pod\_terminal\_changed ```json theme={null} { "data": { "id": "262c2b9c-92f9-46ce-a3f7-e5cb14b1e9b3", "type": "webhook_notification", "attributes": { "id": "262c2b9c-92f9-46ce-a3f7-e5cb14b1e9b3", "event": "container.pod_terminal_changed", "delivery_status": "succeeded", "created_at": "2022-10-21T20:18:14Z" }, "relationships": { "reference_object": { "data": { "id": "9df173e3-96b1-4b41-b0b2-a8459190ffc1", "type": "container_pod_terminal_changed_event" } }, "webhook": { "data": { "id": "33a10002-3bba-486d-b397-1361c4dd4858", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "ecab2629-f537-4a38-9099-cd78a3577fdc", "type": "shipment", "attributes": { "created_at": "2022-10-20T17:02:14Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "CMDUSHZ5223740", "normalized_number": "SHZ5223740", "shipping_line_scac": "CMDU", "shipping_line_name": "CMA CGM", "shipping_line_short_name": "CMA CGM", "customer_name": "Muller, Parisian and Bauch", "port_of_lading_locode": "CNSHK", "port_of_lading_name": "Shekou", "port_of_discharge_locode": "USMIA", "port_of_discharge_name": "Miami Seaport", "pod_vessel_name": "CMA CGM OTELLO", "pod_vessel_imo": "9299628", "pod_voyage_number": "0PGDNE1MA", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": "2022-10-23T05:30:00Z", "pol_atd_at": null, "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-12-16T12:00:00Z", "pod_original_eta_at": "2022-12-16T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T20:18:06Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "7cbb8ba7-66ca-4c6e-84e7-8cfa2686ae3b", "type": "port" } }, "port_of_discharge": { "data": { "id": "ba9cc715-9b4c-4f78-a250-d68e26b23a5a", "type": "port" } }, "pod_terminal": { "data": { "id": "7db4d154-86c1-41e9-aa89-612eeb909f95", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "5820ed38-4b8b-4034-aefa-d5b5dbeb45e9", "type": "container" } ] } }, "links": { "self": "/v2/shipments/d08ffcbf-43c6-4f68-85c4-7f2199211723" } }, { "id": "5820ed38-4b8b-4034-aefa-d5b5dbeb45e9", "type": "container", "attributes": { "number": "TGSU5023798", "seal_number": null, "created_at": "2022-10-20T17:02:14Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "ecab2629-f537-4a38-9099-cd78a3577fdc", "type": "shipment" } }, "pod_terminal": { "data": { "id": "7db4d154-86c1-41e9-aa89-612eeb909f95", "type": "terminal" } }, "transport_events": { "data": [ { "id": "7ef9704f-1b7f-4eb5-b8c3-931fa68d2151", "type": "transport_event" }, { "id": "a5af8967-877e-4078-a5cd-200423ddcba2", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "9338ac85-2509-4d04-a0a4-5d4a572ea172", "type": "raw_event" }, { "id": "c10317c1-11b9-4d1b-b973-42d961da6340", "type": "raw_event" }, { "id": "daa39bfd-042f-487c-9f56-3d18fc7edb32", "type": "raw_event" }, { "id": "0c33d121-291f-4a5d-81d9-6a01f67c67bb", "type": "raw_event" } ] } } }, { "id": "7db4d154-86c1-41e9-aa89-612eeb909f95", "type": "terminal", "attributes": { "id": "7db4d154-86c1-41e9-aa89-612eeb909f95", "nickname": "SFCT", "name": "South Florida Container Terminal", "firms_code": "N775", "smdg_code": null, "bic_facility_code": null, "provided_data": { "pickup_lfd": false, "pickup_lfd_notes": "", "available_for_pickup": false, "fees_at_pod_terminal": false, "holds_at_pod_terminal": false, "pickup_appointment_at": false, "location_at_pod_terminal": false, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": false, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "302 Port Jersey Boulevard", "city": "Jersey City", "state": "New Jersey", "state_abbr": "NJ", "zip": "07305", "country": "United States" }, "relationships": { "port": { "data": { "id": "ba9cc715-9b4c-4f78-a250-d68e26b23a5a", "type": "port" } } } }, { "id": "9df173e3-96b1-4b41-b0b2-a8459190ffc1", "type": "container_pod_terminal_changed_event", "attributes": { "timestamp": "2022-10-21T20:18:14Z", "data_source": "shipping_line" }, "relationships": { "container": { "data": { "id": "5820ed38-4b8b-4034-aefa-d5b5dbeb45e9", "type": "container" } }, "terminal": { "data": { "id": "7db4d154-86c1-41e9-aa89-612eeb909f95", "type": "terminal" } }, "shipment": { "data": { "id": "ecab2629-f537-4a38-9099-cd78a3577fdc", "type": "shipment" } } } } ] } ``` ## container.transport.empty\_in ```json theme={null} { "data": { "id": "7e4e8acf-de36-401d-b3b9-55a5b16adbde", "type": "webhook_notification", "attributes": { "id": "7e4e8acf-de36-401d-b3b9-55a5b16adbde", "event": "container.transport.empty_in", "delivery_status": "succeeded", "created_at": "2022-10-21T20:18:58Z" }, "relationships": { "reference_object": { "data": { "id": "b9936ca0-7e63-48db-8cad-e7d55d756530", "type": "transport_event" } }, "webhook": { "data": { "id": "b485aa7f-042b-49f8-8d81-31fa2c3c79eb", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "f7837cfa-2dc9-4f29-8562-1d1c8882eccd", "type": "shipment", "attributes": { "created_at": "2022-09-23T16:35:47Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "LQ692823", "normalized_number": "MEDULQ692823", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "customer_name": "Zulauf and Sons", "port_of_lading_locode": "ITNAP", "port_of_lading_name": "Naples", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "MSC TIANJIN", "pod_vessel_imo": "9285471", "pod_voyage_number": "237W", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-23T06:30:00Z", "pol_timezone": "Europe/Rome", "pod_eta_at": "2022-10-14T04:00:00Z", "pod_original_eta_at": "2022-10-14T04:00:00Z", "pod_ata_at": "2022-10-14T13:54:01Z", "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T20:18:48Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "bd523255-d320-489e-8710-1ec48ada8e45", "type": "port" } }, "port_of_discharge": { "data": { "id": "74e47232-22a9-4cd5-aef6-30e21d826261", "type": "port" } }, "pod_terminal": { "data": { "id": "774573f6-beb7-4024-9bc4-a29f1d6eaf90", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "fe7e686c-1e34-4181-9333-9ed09c79b159", "type": "container" }, { "id": "4652f270-ce0c-4d89-89e1-bdd0993eac35", "type": "container" }, { "id": "8d460f4d-bf05-41fc-9daf-6afa1917a644", "type": "container" } ] } }, "links": { "self": "/v2/shipments/de8fcacc-0aed-4049-b324-aa65c9c2a765" } }, { "id": "8d460f4d-bf05-41fc-9daf-6afa1917a644", "type": "container", "attributes": { "number": "FSCU8883322", "seal_number": null, "created_at": "2022-09-23T16:35:47Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-14T13:54:01Z", "pod_discharged_at": "2022-10-14T04:00:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": "2022-10-19T17:52:00Z", "empty_terminated_at": "2022-10-21T04:00:00Z", "terminal_checked_at": "2022-10-19T19:24:05Z", "fees_at_pod_terminal": [ ], "pickup_lfd": "2022-10-20T04:00:00Z", "pickup_appointment_at": "2022-10-19T16:00:00Z", "pod_full_out_chassis_number": "OWNCHASSIS", "location_at_pod_terminal": "COMMUNITY - OUT", "pod_last_tracking_request_at": "2022-10-19T19:24:04Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "f7837cfa-2dc9-4f29-8562-1d1c8882eccd", "type": "shipment" } }, "pod_terminal": { "data": { "id": "774573f6-beb7-4024-9bc4-a29f1d6eaf90", "type": "terminal" } }, "transport_events": { "data": [ { "id": "91646567-40a8-42cf-93e1-6016b1274568", "type": "transport_event" }, { "id": "1313d847-66c0-425a-b797-4796275a8c41", "type": "transport_event" }, { "id": "61b832bf-031c-4296-8ca4-8b8f256a9fe1", "type": "transport_event" }, { "id": "747d7cc1-82b7-4183-bbb7-356b6d5e025d", "type": "transport_event" }, { "id": "0d2b94be-dea6-4d63-97c1-f21b7d5e767b", "type": "transport_event" }, { "id": "f53f143e-9f85-4fa2-a0df-6e25c4bfbc87", "type": "transport_event" }, { "id": "38cb8320-de6a-4385-a626-71d59473d5ff", "type": "transport_event" }, { "id": "b9936ca0-7e63-48db-8cad-e7d55d756530", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "e0e35bdd-fd6d-41cb-b39c-3d4f7c8ce758", "type": "raw_event" }, { "id": "5def6df9-2878-46cb-8648-69b157bd0993", "type": "raw_event" }, { "id": "20decd2c-3e2f-463d-a270-d249fd0bdbdb", "type": "raw_event" }, { "id": "260e6094-dfbb-40c1-ad90-37c1627b778d", "type": "raw_event" }, { "id": "264f4d56-7c1b-4550-830f-c26b1448cce1", "type": "raw_event" }, { "id": "1d20551a-dfe9-4584-baae-d0288f7342e8", "type": "raw_event" }, { "id": "c5baa1c6-0255-444f-afe6-65db202c33fb", "type": "raw_event" }, { "id": "09554878-a1b5-4c0f-972e-8250163a6be4", "type": "raw_event" }, { "id": "59974058-689b-4052-8598-592aa2c999fa", "type": "raw_event" }, { "id": "00081755-7c93-421a-9a0b-5adf01f1051e", "type": "raw_event" } ] } } }, { "id": "74e47232-22a9-4cd5-aef6-30e21d826261", "type": "port", "attributes": { "id": "74e47232-22a9-4cd5-aef6-30e21d826261", "name": "New York / New Jersey", "code": "USNYC", "state_abbr": "NY", "city": "New York", "country_code": "US", "latitude": "40.684996498", "longitude": "-74.151115685", "time_zone": "America/New_York" } }, { "id": "b9936ca0-7e63-48db-8cad-e7d55d756530", "type": "transport_event", "attributes": { "event": "container.transport.empty_in", "created_at": "2022-10-21T20:18:58Z", "voyage_number": null, "timestamp": "2022-10-21T04:00:00Z", "data_source": "shipping_line", "location_locode": "USNYC", "timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "f7837cfa-2dc9-4f29-8562-1d1c8882eccd", "type": "shipment" } }, "container": { "data": { "id": "8d460f4d-bf05-41fc-9daf-6afa1917a644", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "74e47232-22a9-4cd5-aef6-30e21d826261", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.empty\_out ```json theme={null} { "data": { "id": "6dded288-6b72-483a-9f33-c79aa8e9c1ff", "type": "webhook_notification", "attributes": { "id": "6dded288-6b72-483a-9f33-c79aa8e9c1ff", "event": "container.transport.empty_out", "delivery_status": "succeeded", "created_at": "2022-10-21T20:17:02Z" }, "relationships": { "reference_object": { "data": { "id": "fb7533ea-7afc-4a7c-a831-0b36bd28bf26", "type": "transport_event" } }, "webhook": { "data": { "id": "feb4bb16-deff-4249-8fc6-5ae67c2fe8d2", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "1fe11df6-143d-4d6c-bbc8-b5963e19611f", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:16:02Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "SA00846884", "normalized_number": "SA00846884", "shipping_line_scac": "ACLU", "shipping_line_name": "Atlantic Container Line", "shipping_line_short_name": "ACL", "customer_name": "Stracke Inc", "port_of_lading_locode": "BEANR", "port_of_lading_name": "Antwerp", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": null, "pod_vessel_imo": null, "pod_voyage_number": null, "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": "2022-11-04T13:00:00Z", "pol_atd_at": null, "pol_timezone": "Europe/Brussels", "pod_eta_at": "2022-11-15T00:00:00Z", "pod_original_eta_at": "2022-11-15T00:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "fc6a6c8c-4f6f-459b-be6c-814d34ec312b", "type": "port" } }, "port_of_discharge": { "data": { "id": "dfcc3bcd-a63d-4481-b68b-a91da48b5d79", "type": "port" } }, "pod_terminal": { "data": null }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "3f92cb0c-b7b2-4f08-ae65-677fc4d7712d", "type": "container" } ] } }, "links": { "self": "/v2/shipments/6e9625a2-ea71-49ad-8441-13a3a44926f2" } }, { "id": "3f92cb0c-b7b2-4f08-ae65-677fc4d7712d", "type": "container", "attributes": { "number": "GCNU8802957", "seal_number": null, "created_at": "2022-10-21T20:16:02Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "1fe11df6-143d-4d6c-bbc8-b5963e19611f", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "fb7533ea-7afc-4a7c-a831-0b36bd28bf26", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "e453e33d-3ef7-4fdb-b012-e83ba5903466", "type": "raw_event" } ] } } }, { "id": "2381793f-8f43-4bd1-a4e0-1135c322f441", "type": "metro_area", "attributes": { "id": "2381793f-8f43-4bd1-a4e0-1135c322f441", "name": "Antwerp Churchill Terminal", "state_abbr": "Vlaanderen", "code": "BEANT", "latitude": "51.2806024", "longitude": "4.3551883", "country_code": "BE", "time_zone": "Europe/Brussels" } }, { "id": "fb7533ea-7afc-4a7c-a831-0b36bd28bf26", "type": "transport_event", "attributes": { "event": "container.transport.empty_out", "created_at": "2022-10-21T20:16:02Z", "voyage_number": null, "timestamp": "2022-10-20T11:12:00Z", "data_source": "shipping_line", "location_locode": "BEANT", "timezone": "Europe/Brussels" }, "relationships": { "shipment": { "data": { "id": "1fe11df6-143d-4d6c-bbc8-b5963e19611f", "type": "shipment" } }, "container": { "data": { "id": "3f92cb0c-b7b2-4f08-ae65-677fc4d7712d", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "2381793f-8f43-4bd1-a4e0-1135c322f441", "type": "metro_area" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.full\_in ```json theme={null} { "data": { "id": "63fb3158-375e-417f-a31e-baba60a17afa", "type": "webhook_notification", "attributes": { "id": "63fb3158-375e-417f-a31e-baba60a17afa", "event": "container.transport.full_in", "delivery_status": "succeeded", "created_at": "2022-10-21T20:18:14Z" }, "relationships": { "reference_object": { "data": { "id": "83e82be7-1791-48cd-a595-e4c92c3ddd09", "type": "transport_event" } }, "webhook": { "data": { "id": "fad16f92-e418-49eb-b004-55eeff8e28c6", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "84aedf7a-a3ec-48e6-bc36-e3234454795c", "type": "shipment", "attributes": { "created_at": "2022-10-20T17:02:14Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "CMDUSHZ5223740", "normalized_number": "SHZ5223740", "shipping_line_scac": "CMDU", "shipping_line_name": "CMA CGM", "shipping_line_short_name": "CMA CGM", "customer_name": "Kris LLC", "port_of_lading_locode": "CNSHK", "port_of_lading_name": "Shekou", "port_of_discharge_locode": "USMIA", "port_of_discharge_name": "Miami Seaport", "pod_vessel_name": "CMA CGM OTELLO", "pod_vessel_imo": "9299628", "pod_voyage_number": "0PGDNE1MA", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": "2022-10-23T05:30:00Z", "pol_atd_at": null, "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-12-16T12:00:00Z", "pod_original_eta_at": "2022-12-16T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T20:18:06Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "57f55608-c9fb-47d1-8cd6-0e78b340061b", "type": "port" } }, "port_of_discharge": { "data": { "id": "b802e728-e01a-400f-9687-81e9d7f4da51", "type": "port" } }, "pod_terminal": { "data": { "id": "21ff320e-ddb7-4199-8873-a819e9dcfc31", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "975be82b-d16a-4b0f-818a-ea1ba83c3fde", "type": "container" } ] } }, "links": { "self": "/v2/shipments/d08ffcbf-43c6-4f68-85c4-7f2199211723" } }, { "id": "975be82b-d16a-4b0f-818a-ea1ba83c3fde", "type": "container", "attributes": { "number": "TGSU5023798", "seal_number": null, "created_at": "2022-10-20T17:02:14Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "84aedf7a-a3ec-48e6-bc36-e3234454795c", "type": "shipment" } }, "pod_terminal": { "data": { "id": "21ff320e-ddb7-4199-8873-a819e9dcfc31", "type": "terminal" } }, "transport_events": { "data": [ { "id": "3a60833d-df16-438d-ad8e-5b3d9a1c44ed", "type": "transport_event" }, { "id": "83e82be7-1791-48cd-a595-e4c92c3ddd09", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "ffbab92a-7f6d-45f3-bfa1-c88a79feb19c", "type": "raw_event" }, { "id": "2323c45e-a4ab-42fc-95a7-5b4f14af6835", "type": "raw_event" }, { "id": "64bd26a3-8393-41bb-ab7c-64b8d705d054", "type": "raw_event" }, { "id": "2e08535f-7a3f-4dc1-87f9-939101e46d53", "type": "raw_event" } ] } } }, { "id": "57f55608-c9fb-47d1-8cd6-0e78b340061b", "type": "port", "attributes": { "id": "57f55608-c9fb-47d1-8cd6-0e78b340061b", "name": "Shekou", "code": "CNSHK", "state_abbr": null, "city": null, "country_code": "CN", "latitude": "22.459940331", "longitude": "113.892910965", "time_zone": "Asia/Shanghai" } }, { "id": "83e82be7-1791-48cd-a595-e4c92c3ddd09", "type": "transport_event", "attributes": { "event": "container.transport.full_in", "created_at": "2022-10-21T20:18:14Z", "voyage_number": null, "timestamp": "2022-10-20T16:29:00Z", "data_source": "shipping_line", "location_locode": "CNSHK", "timezone": "Asia/Shanghai" }, "relationships": { "shipment": { "data": { "id": "84aedf7a-a3ec-48e6-bc36-e3234454795c", "type": "shipment" } }, "container": { "data": { "id": "975be82b-d16a-4b0f-818a-ea1ba83c3fde", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "57f55608-c9fb-47d1-8cd6-0e78b340061b", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.full\_out ```json theme={null} { "data": { "id": "bef3aef4-6e81-4824-8bf6-44e1cffa41a7", "type": "webhook_notification", "attributes": { "id": "bef3aef4-6e81-4824-8bf6-44e1cffa41a7", "event": "container.transport.full_out", "delivery_status": "succeeded", "created_at": "2022-10-21T20:19:06Z" }, "relationships": { "reference_object": { "data": { "id": "65f4a065-a9f3-4f2e-b060-0e3d857ed67f", "type": "transport_event" } }, "webhook": { "data": { "id": "715b8e22-2671-45a8-972c-76784feca537", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "e0afd8d9-a942-480b-8902-03aec602808d", "type": "shipment", "attributes": { "created_at": "2022-09-12T02:12:39Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "MAEUGAP001939", "normalized_number": "GAP001939", "shipping_line_scac": "MAEU", "shipping_line_name": "Maersk", "shipping_line_short_name": "Maersk", "customer_name": "Shields, Pollich and Stoltenberg", "port_of_lading_locode": "CNYTN", "port_of_lading_name": "Yantian", "port_of_discharge_locode": "USSAV", "port_of_discharge_name": "Savannah", "pod_vessel_name": "GLEN CANYON", "pod_vessel_imo": "9302097", "pod_voyage_number": "003E", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-10T01:08:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-10-19T10:00:00Z", "pod_original_eta_at": "2022-10-18T10:00:00Z", "pod_ata_at": "2022-10-19T10:00:00Z", "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T20:19:02Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": "2022-10-21T20:19:06Z", "line_tracking_stopped_reason": "all_containers_terminated" }, "relationships": { "port_of_lading": { "data": { "id": "cdf4a74f-5c13-48f0-92e7-4a7704d2030f", "type": "port" } }, "port_of_discharge": { "data": { "id": "f15826a5-d826-4845-8aaa-9f295b36397b", "type": "port" } }, "pod_terminal": { "data": { "id": "db19e898-22b3-44a9-ba61-3a4dbf4018e6", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "2ca3f310-4d0c-4b4f-8dcd-8b8d19f60fb8", "type": "container" } ] } }, "links": { "self": "/v2/shipments/4a97efa3-2383-41b8-87f3-3ae1fe81d429" } }, { "id": "2ca3f310-4d0c-4b4f-8dcd-8b8d19f60fb8", "type": "container", "attributes": { "number": "MSKU8532556", "seal_number": null, "created_at": "2022-09-12T02:12:39Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-19T10:00:00Z", "pod_discharged_at": "2022-10-20T06:01:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": null, "pod_full_out_at": "2022-10-21T15:05:00Z", "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T03:31:42Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "Yard", "pod_last_tracking_request_at": "2022-10-21T03:31:29Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "e0afd8d9-a942-480b-8902-03aec602808d", "type": "shipment" } }, "pod_terminal": { "data": { "id": "db19e898-22b3-44a9-ba61-3a4dbf4018e6", "type": "terminal" } }, "transport_events": { "data": [ { "id": "b9c685dc-0556-4b68-a9d5-f4747fcb9611", "type": "transport_event" }, { "id": "cab0d40f-ce6f-4170-bf08-d573a484944e", "type": "transport_event" }, { "id": "aa4ef47b-77b2-42c7-b81f-3dc2b1ead4a8", "type": "transport_event" }, { "id": "5f75e4b6-f139-4314-930c-e79efdd7b254", "type": "transport_event" }, { "id": "693b3062-6520-4390-a827-2dd390dbbc44", "type": "transport_event" }, { "id": "41270e3a-ee02-41c1-9135-3fb174bac54b", "type": "transport_event" }, { "id": "65f4a065-a9f3-4f2e-b060-0e3d857ed67f", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "a74dbeaf-8a2f-4409-8580-d049f131c7ae", "type": "raw_event" }, { "id": "0b500fb5-1613-4066-8b42-33d9d07e021f", "type": "raw_event" }, { "id": "3072849e-3031-427d-9e96-aa5ec6b8ca4f", "type": "raw_event" }, { "id": "c6e6023b-1b50-4ea5-aaf1-b6b9f1c184ef", "type": "raw_event" }, { "id": "7bccb807-404c-48c9-93df-3f3dcc754eb2", "type": "raw_event" }, { "id": "8226d324-42b0-480e-bc15-0d34bc73fde5", "type": "raw_event" }, { "id": "fdf27063-1a8c-48e7-afae-dc64d48346fb", "type": "raw_event" } ] } } }, { "id": "f15826a5-d826-4845-8aaa-9f295b36397b", "type": "port", "attributes": { "id": "f15826a5-d826-4845-8aaa-9f295b36397b", "name": "Savannah", "code": "USSAV", "state_abbr": "GA", "city": "Savannah", "country_code": "US", "latitude": "32.128923976", "longitude": "-81.140998396", "time_zone": "America/New_York" } }, { "id": "db19e898-22b3-44a9-ba61-3a4dbf4018e6", "type": "terminal", "attributes": { "id": "db19e898-22b3-44a9-ba61-3a4dbf4018e6", "nickname": "GCT", "name": "Garden City Terminals", "firms_code": "L737", "smdg_code": null, "bic_facility_code": null, "provided_data": { "pickup_lfd": false, "pickup_lfd_notes": "", "available_for_pickup": false, "fees_at_pod_terminal": false, "holds_at_pod_terminal": false, "pickup_appointment_at": false, "location_at_pod_terminal": false, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": false, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "701 New Dock Street Berths 212-225", "city": "Terminal Island", "state": "California", "state_abbr": "CA", "zip": "90731", "country": "United States" }, "relationships": { "port": { "data": { "id": "f15826a5-d826-4845-8aaa-9f295b36397b", "type": "port" } } } }, { "id": "65f4a065-a9f3-4f2e-b060-0e3d857ed67f", "type": "transport_event", "attributes": { "event": "container.transport.full_out", "created_at": "2022-10-21T20:19:06Z", "voyage_number": null, "timestamp": "2022-10-21T15:05:00Z", "data_source": "shipping_line", "location_locode": "USSAV", "timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "e0afd8d9-a942-480b-8902-03aec602808d", "type": "shipment" } }, "container": { "data": { "id": "2ca3f310-4d0c-4b4f-8dcd-8b8d19f60fb8", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "f15826a5-d826-4845-8aaa-9f295b36397b", "type": "port" } }, "terminal": { "data": { "id": "db19e898-22b3-44a9-ba61-3a4dbf4018e6", "type": "terminal" } } } } ] } ``` ## container.transport.rail\_arrived ```json theme={null} { "data": { "id": "83cc76e6-64c9-4a47-ab7a-b1a796016041", "type": "webhook_notification", "attributes": { "id": "83cc76e6-64c9-4a47-ab7a-b1a796016041", "event": "container.transport.rail_arrived", "delivery_status": "pending", "created_at": "2022-10-21T20:18:00Z" }, "relationships": { "reference_object": { "data": { "id": "7120723d-7bbd-43a8-bbd2-69d742ba76ae", "type": "transport_event" } }, "webhook": { "data": { "id": "72e27eda-f3ff-47f4-9ebd-04e4c82e411f", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "a8a97ac7-648b-42fa-9629-ecbd323a2cd6", "type": "shipment", "attributes": { "created_at": "2022-09-28T14:19:08Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "OOLU2706578920", "normalized_number": "2706578920", "shipping_line_scac": "OOLU", "shipping_line_name": "Orient Overseas Container Line", "shipping_line_short_name": "OOCL", "customer_name": "Heller, Hansen and Schumm", "port_of_lading_locode": "TWKHH", "port_of_lading_name": "Kaohsiung", "port_of_discharge_locode": "USLGB", "port_of_discharge_name": "Long Beach", "pod_vessel_name": "COSCO ENGLAND", "pod_vessel_imo": "9516428", "pod_voyage_number": "054E", "destination_locode": "USEWI", "destination_name": "Elwood", "destination_timezone": "America/Chicago", "destination_ata_at": "2022-10-21T17:43:00Z", "destination_eta_at": "2022-10-18T09:36:00Z", "pol_etd_at": null, "pol_atd_at": "2022-09-27T02:05:00Z", "pol_timezone": "Asia/Taipei", "pod_eta_at": "2022-10-12T14:00:00Z", "pod_original_eta_at": "2022-10-10T15:00:00Z", "pod_ata_at": "2022-10-12T13:26:00Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:17:48Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "0233b87d-833e-45bb-ae74-83fd69200d81", "type": "port" } }, "port_of_discharge": { "data": { "id": "f8361d18-09c2-4aff-a933-ca2c22919532", "type": "port" } }, "pod_terminal": { "data": { "id": "d9bf35cd-3bb6-4235-96ca-b57665173c11", "type": "terminal" } }, "destination": { "data": { "id": "ad3c66a7-2580-4757-90f4-5f28c2892468", "type": "metro_area" } }, "destination_terminal": { "data": { "id": "cac87536-25db-4d4f-bb15-3a674d67d31f", "type": "rail_terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "e25ff651-f58f-4165-8e97-aa2ad73027be", "type": "container" } ] } }, "links": { "self": "/v2/shipments/7ffaff8a-8004-4c02-8acf-3d744708e0b4" } }, { "id": "e25ff651-f58f-4165-8e97-aa2ad73027be", "type": "container", "attributes": { "number": "OOLU6213464", "seal_number": null, "created_at": "2022-09-28T14:19:08Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-12T13:26:00Z", "pod_discharged_at": "2022-10-12T22:27:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ { "status": "hold", "name": "other", "description": "ONDOCK" }, { "status": "hold", "name": "other", "description": "CTF_CONTAINER_HOLD" }, { "status": "hold", "name": "freight", "description": "FREIGHT_BL_HOLD" } ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 56879, "pod_full_out_at": "2022-10-14T16:21:00Z", "empty_terminated_at": null, "terminal_checked_at": "2022-10-14T20:50:59Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "GROUNDED", "pod_last_tracking_request_at": "2022-10-14T20:50:59Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": "America/Chicago", "empty_terminated_timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "a8a97ac7-648b-42fa-9629-ecbd323a2cd6", "type": "shipment" } }, "pod_terminal": { "data": { "id": "d9bf35cd-3bb6-4235-96ca-b57665173c11", "type": "terminal" } }, "transport_events": { "data": [ { "id": "78941fc1-91e0-440a-84d2-b87106a854ba", "type": "transport_event" }, { "id": "60898751-f616-45b1-942e-a65aa7c9ee96", "type": "transport_event" }, { "id": "7bc2b53a-7638-47d8-9820-0cfbf1ef5300", "type": "transport_event" }, { "id": "8cb669fb-9dde-4f2c-b35e-47c460f3e650", "type": "transport_event" }, { "id": "f33ccf00-c8e8-4712-a323-2f43245e5fe6", "type": "transport_event" }, { "id": "20a936fb-b0e2-49ff-a2a7-7ea3c3ae91a6", "type": "transport_event" }, { "id": "f5392045-0e24-46cb-8984-72642844d373", "type": "transport_event" }, { "id": "a3bf7950-1cf6-43fb-859d-ef35610b7d26", "type": "transport_event" }, { "id": "cb8f07dd-8be4-4743-95d9-704da3d788de", "type": "transport_event" }, { "id": "02f73f8c-26ad-48e3-b4a4-e127ded9dfc6", "type": "transport_event" }, { "id": "ce57263a-d817-46fd-9f26-b9290d555b47", "type": "transport_event" }, { "id": "d5274b77-2829-4b03-b466-d6bb3685811a", "type": "transport_event" }, { "id": "8bb29b9a-f49a-42a3-9381-7bd9fe1245b9", "type": "transport_event" }, { "id": "7120723d-7bbd-43a8-bbd2-69d742ba76ae", "type": "transport_event" }, { "id": "7dc68b35-48f4-4941-b7a4-3b6c5ee63871", "type": "transport_event" }, { "id": "7233a3af-1d0b-4725-a15c-1e303f5b5e49", "type": "transport_event" }, { "id": "57687dd8-b5f1-4fd8-bf77-e9e801991084", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "a0fd66f6-6787-45c4-8b98-b1534f8b0598", "type": "raw_event" }, { "id": "5caa8987-0847-4453-a9fd-df68d963785f", "type": "raw_event" }, { "id": "b5efac1c-c773-46c7-ae41-cc7e7bc3059c", "type": "raw_event" }, { "id": "35074992-a17b-4a85-97f2-9ffe9620bc5f", "type": "raw_event" }, { "id": "209702ed-0fad-43d9-a092-20b5a46b5ad6", "type": "raw_event" }, { "id": "9fe50c8e-5584-4491-a8d6-c30ef8cffa11", "type": "raw_event" }, { "id": "cd36808d-3dc7-486f-b0a8-082b879f115c", "type": "raw_event" }, { "id": "a7c6ead4-e104-4b51-aa28-fc4b7cc95494", "type": "raw_event" }, { "id": "61c4afd6-d5f5-4eec-b8fd-e3fd2bcab381", "type": "raw_event" }, { "id": "fa6d887d-77ed-49b3-8ce4-4b7856d55a70", "type": "raw_event" }, { "id": "59f40a9b-cf7a-494e-a251-d47ae1bc28c0", "type": "raw_event" }, { "id": "0eb7e500-94cc-4a50-ac16-6d207edd2a48", "type": "raw_event" }, { "id": "c71761fc-2330-455e-b4b2-20b5b4e35800", "type": "raw_event" }, { "id": "e1e33733-23f3-44a7-a683-c79f7e1c36a6", "type": "raw_event" }, { "id": "6ed36430-f0a6-49eb-96dc-b67bebd58ffa", "type": "raw_event" }, { "id": "d0c88cb3-ca75-4216-bfb6-a3305156bb29", "type": "raw_event" }, { "id": "c3d046cc-56ae-487a-9ac3-5d3b00edb5a4", "type": "raw_event" }, { "id": "ec3f15e1-b342-454f-8d85-8d7495ca3767", "type": "raw_event" }, { "id": "311a1b33-2341-4342-b5e7-6b42bdb4d5d1", "type": "raw_event" }, { "id": "c6a819c6-97db-4894-ab70-6be34f1cf2a3", "type": "raw_event" }, { "id": "1a57d88a-789a-44ad-a1ec-f97cf8561090", "type": "raw_event" }, { "id": "36d04b27-9f8d-493c-8df6-d435f0f50293", "type": "raw_event" }, { "id": "7af8c6df-45a6-4fb4-8bd6-cda6726a428a", "type": "raw_event" }, { "id": "ad3aa77e-4d12-4772-bf01-ca0ca98d91ed", "type": "raw_event" }, { "id": "e86c02d2-577d-49f8-9c86-5632b8ab0fe7", "type": "raw_event" }, { "id": "f159db75-2e5e-45e9-bffc-3879bca1cc5c", "type": "raw_event" }, { "id": "f605cfd9-a956-4051-b209-b83b83c459c7", "type": "raw_event" }, { "id": "e12a406b-a3f6-40e3-a771-31e7596f94b8", "type": "raw_event" } ] } } }, { "id": "ad3c66a7-2580-4757-90f4-5f28c2892468", "type": "metro_area", "attributes": { "id": "ad3c66a7-2580-4757-90f4-5f28c2892468", "name": "Elwood", "state_abbr": "IL", "code": "USEWI", "latitude": "41.4039201", "longitude": "-88.1117242", "country_code": "US", "time_zone": "America/Chicago" } }, { "id": "cac87536-25db-4d4f-bb15-3a674d67d31f", "type": "rail_terminal", "attributes": { "id": "cac87536-25db-4d4f-bb15-3a674d67d31f", "nickname": "BNSF", "name": "BNSF - Logistics Park Chicago (LPC) Intermodal Facility", "city": "Elwood", "firms_code": "H572" }, "relationships": { "metro_area": { "data": { "id": "ad3c66a7-2580-4757-90f4-5f28c2892468", "type": "metro_area" } }, "port": { "data": null } } }, { "id": "7120723d-7bbd-43a8-bbd2-69d742ba76ae", "type": "transport_event", "attributes": { "event": "container.transport.rail_arrived", "created_at": "2022-10-21T20:18:00Z", "voyage_number": null, "timestamp": "2022-10-21T17:43:00Z", "data_source": "shipping_line", "location_locode": "USEWI", "timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "a8a97ac7-648b-42fa-9629-ecbd323a2cd6", "type": "shipment" } }, "container": { "data": { "id": "e25ff651-f58f-4165-8e97-aa2ad73027be", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "ad3c66a7-2580-4757-90f4-5f28c2892468", "type": "metro_area" } }, "terminal": { "data": { "id": "cac87536-25db-4d4f-bb15-3a674d67d31f", "type": "rail_terminal" } } } } ] } ``` ## container.transport.rail\_departed ```json theme={null} { "data": { "id": "176364d2-7f63-4382-8fba-da24e3c14057", "type": "webhook_notification", "attributes": { "id": "176364d2-7f63-4382-8fba-da24e3c14057", "event": "container.transport.rail_departed", "delivery_status": "succeeded", "created_at": "2022-10-21T20:15:29Z" }, "relationships": { "reference_object": { "data": { "id": "7ee8aae1-14da-491a-81fc-6c98ed89775f", "type": "transport_event" } }, "webhook": { "data": { "id": "90c5b9c3-366f-49fb-bbf5-df024f1848d4", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "015c921e-ecdf-4491-982e-89152288f3ae", "type": "shipment", "attributes": { "created_at": "2022-09-20T08:00:59Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "2706772870", "normalized_number": "2706772870", "shipping_line_scac": "OOLU", "shipping_line_name": "Orient Overseas Container Line", "shipping_line_short_name": "OOCL", "customer_name": "Brekke Inc", "port_of_lading_locode": "CNYTN", "port_of_lading_name": "Yantian", "port_of_discharge_locode": "USLGB", "port_of_discharge_name": "Long Beach", "pod_vessel_name": "COSCO ENGLAND", "pod_vessel_imo": "9516428", "pod_voyage_number": "054E", "destination_locode": "USEWI", "destination_name": "Elwood", "destination_timezone": "America/Chicago", "destination_ata_at": null, "destination_eta_at": "2022-10-25T00:50:00Z", "pol_etd_at": "2022-09-25T10:00:00Z", "pol_atd_at": "2022-09-25T10:41:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-10-12T14:00:00Z", "pod_original_eta_at": "2022-10-09T15:00:00Z", "pod_ata_at": "2022-10-12T13:26:00Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:15:13Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "fcc475e5-9625-4632-815e-bd84db28ed4e", "type": "port" } }, "port_of_discharge": { "data": { "id": "39425403-9982-47f1-9988-6b73f400b9ba", "type": "port" } }, "pod_terminal": { "data": { "id": "b0765575-ee97-45e4-a2c8-e9a11c969b37", "type": "terminal" } }, "destination": { "data": { "id": "239ca895-c67b-4563-b496-821833d03272", "type": "metro_area" } }, "destination_terminal": { "data": { "id": "e8e91a82-44ac-4690-baed-2f0998c2d303", "type": "rail_terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "600785bd-04b3-48be-b2a5-37264ba9fc74", "type": "container" } ] } }, "links": { "self": "/v2/shipments/0372dba4-f153-44e1-a2d0-e6f444658b60" } }, { "id": "600785bd-04b3-48be-b2a5-37264ba9fc74", "type": "container", "attributes": { "number": "OOCU7853330", "seal_number": null, "created_at": "2022-09-20T08:00:59Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-12T13:26:00Z", "pod_discharged_at": "2022-10-14T02:56:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ { "status": "hold", "name": "other", "description": "ONDOCK" }, { "status": "hold", "name": "other", "description": "CTF_CONTAINER_HOLD" }, { "status": "hold", "name": "freight", "description": "FREIGHT_BL_HOLD" } ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 45101, "pod_full_out_at": "2022-10-20T20:41:00Z", "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T00:19:37Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "GROUNDED", "pod_last_tracking_request_at": "2022-10-21T00:19:36Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": "America/Chicago", "empty_terminated_timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "015c921e-ecdf-4491-982e-89152288f3ae", "type": "shipment" } }, "pod_terminal": { "data": { "id": "b0765575-ee97-45e4-a2c8-e9a11c969b37", "type": "terminal" } }, "transport_events": { "data": [ { "id": "521f72b5-aee1-4857-859d-a03c6a1d79f1", "type": "transport_event" }, { "id": "ea94574e-dab4-4751-90f7-32be994c15a2", "type": "transport_event" }, { "id": "95dd1b3c-04e2-4587-85c3-9458684792e8", "type": "transport_event" }, { "id": "6791ad37-3316-4f27-b3f4-78be3411e791", "type": "transport_event" }, { "id": "b87c94b6-237b-4140-a3a0-56b10f402a2a", "type": "transport_event" }, { "id": "fa4d115d-6cfc-4584-8658-1175bf7cb31e", "type": "transport_event" }, { "id": "278a247c-6561-4b9a-a251-27024ffef12b", "type": "transport_event" }, { "id": "24dca556-e1be-4963-84e0-dec6e4419dd8", "type": "transport_event" }, { "id": "7ee8aae1-14da-491a-81fc-6c98ed89775f", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "f8ce10b7-eed3-46c5-9ee9-91a23dbb70b1", "type": "raw_event" }, { "id": "c84461fe-2920-4d06-8868-4f2609b8a773", "type": "raw_event" }, { "id": "0d387d25-6fc1-4e29-a0df-2cd0b09a46e6", "type": "raw_event" }, { "id": "ac549216-841e-4d24-ab39-605b01ed8843", "type": "raw_event" }, { "id": "e12200c1-a077-460f-bac7-907683198b8b", "type": "raw_event" }, { "id": "3b8d212c-973a-42b6-b773-aa0ce4716e89", "type": "raw_event" }, { "id": "fd40180b-9aff-4d17-b508-4bfa6d205f6d", "type": "raw_event" }, { "id": "797a3eb1-d8cd-4011-ae63-bcd4437ea402", "type": "raw_event" }, { "id": "864089e6-61dd-4533-9d27-dc639bda8eee", "type": "raw_event" }, { "id": "1cbd85c2-177a-4ac1-bc25-dab6970da97c", "type": "raw_event" }, { "id": "cb5e6908-5add-4e99-b386-eb45a4bcf1f4", "type": "raw_event" }, { "id": "8fbe4b5a-dd3c-425e-96fd-d796b016792a", "type": "raw_event" }, { "id": "1dcaaa69-4aa0-4a30-849a-8e1e4b16c885", "type": "raw_event" } ] } } }, { "id": "9b98ee7b-6e2a-4eaa-9d23-2e0b8e911e92", "type": "port", "attributes": { "id": "9b98ee7b-6e2a-4eaa-9d23-2e0b8e911e92", "name": "Los Angeles", "code": "USLAX", "state_abbr": "CA", "city": "Los Angeles", "country_code": "US", "latitude": "33.728193631", "longitude": "-118.255820307", "time_zone": "America/Los_Angeles" } }, { "id": "7ee8aae1-14da-491a-81fc-6c98ed89775f", "type": "transport_event", "attributes": { "event": "container.transport.rail_departed", "created_at": "2022-10-21T20:15:29Z", "voyage_number": null, "timestamp": "2022-10-21T19:03:00Z", "data_source": "shipping_line", "location_locode": "USLAX", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "015c921e-ecdf-4491-982e-89152288f3ae", "type": "shipment" } }, "container": { "data": { "id": "600785bd-04b3-48be-b2a5-37264ba9fc74", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "9b98ee7b-6e2a-4eaa-9d23-2e0b8e911e92", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.rail\_loaded ```json theme={null} { "data": { "id": "dc507a07-9749-40b5-8481-fa4c539df722", "type": "webhook_notification", "attributes": { "id": "dc507a07-9749-40b5-8481-fa4c539df722", "event": "container.transport.rail_loaded", "delivery_status": "succeeded", "created_at": "2022-10-21T19:29:49Z" }, "relationships": { "reference_object": { "data": { "id": "4c6c85eb-79bc-4f7c-ad66-962a6ab3a506", "type": "transport_event" } }, "webhook": { "data": { "id": "22cd79b4-3d37-4f34-a990-3f378760dd89", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "93921adf-af96-4096-9797-2abea7e95e79", "type": "shipment", "attributes": { "created_at": "2022-10-04T22:00:30Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "6344045750", "normalized_number": "6344045750", "shipping_line_scac": "COSU", "shipping_line_name": "COSCO", "shipping_line_short_name": "COSCO", "customer_name": "Hilll, Boyle and Hagenes", "port_of_lading_locode": "CNSGH", "port_of_lading_name": "Shanghai", "port_of_discharge_locode": "CAVAN", "port_of_discharge_name": "Vancouver", "pod_vessel_name": "APL COLUMBUS", "pod_vessel_imo": "9597525", "pod_voyage_number": "0TN7VS1MA", "destination_locode": "USCHI", "destination_name": "Chicago", "destination_timezone": "America/Chicago", "destination_ata_at": null, "destination_eta_at": "2022-10-30T02:50:00Z", "pol_etd_at": null, "pol_atd_at": "2022-09-23T00:17:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-10-19T13:00:00Z", "pod_original_eta_at": "2022-10-18T12:00:00Z", "pod_ata_at": "2022-10-19T13:49:00Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T19:29:46Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "6ec66cea-7a35-4522-98cd-52246198502b", "type": "port" } }, "port_of_discharge": { "data": { "id": "a1edd1e9-61b0-429c-a05a-31ac8d9d2b8b", "type": "port" } }, "pod_terminal": { "data": { "id": "c989c2e6-c933-4ca9-98a5-a0418254b218", "type": "terminal" } }, "destination": { "data": { "id": "83b8c829-08d7-4b02-be09-a515b33f4237", "type": "metro_area" } }, "destination_terminal": { "data": { "id": "79fdf215-b32b-4a7b-99c5-1e44df0dcd76", "type": "rail_terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "3be28cd9-165f-4af1-827a-902bef0147d0", "type": "container" } ] } }, "links": { "self": "/v2/shipments/5d990a0a-a854-4bf2-acd4-abc96d98da29" } }, { "id": "3be28cd9-165f-4af1-827a-902bef0147d0", "type": "container", "attributes": { "number": "FFAU3144344", "seal_number": "22626037", "created_at": "2022-10-04T22:00:30Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-19T13:49:00Z", "pod_discharged_at": "2022-10-20T20:25:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 35598, "pod_full_out_at": "2022-10-21T18:30:00Z", "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T18:24:07Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "RAIL", "pod_last_tracking_request_at": "2022-10-21T18:24:07Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": "America/Chicago", "empty_terminated_timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "93921adf-af96-4096-9797-2abea7e95e79", "type": "shipment" } }, "pod_terminal": { "data": { "id": "c989c2e6-c933-4ca9-98a5-a0418254b218", "type": "terminal" } }, "transport_events": { "data": [ { "id": "462c6724-d4fc-4b3f-ae7e-1bb2f4ed9321", "type": "transport_event" }, { "id": "afa7595d-e6ea-4e99-8af9-a8d6d3269adb", "type": "transport_event" }, { "id": "5e36ae0c-bf1d-4993-8f58-cf2b3efc440a", "type": "transport_event" }, { "id": "6e4b9563-5b52-4d45-b3c6-a5111c14564d", "type": "transport_event" }, { "id": "ad1a0236-d071-41ac-bad4-dacecc245fc1", "type": "transport_event" }, { "id": "6195bd49-f61d-4f7e-9587-0ee03541b1d7", "type": "transport_event" }, { "id": "4353904b-a40b-494a-a13b-ad85141082d5", "type": "transport_event" }, { "id": "4c6c85eb-79bc-4f7c-ad66-962a6ab3a506", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "45f8bc1e-9a29-4505-b534-f6832a62c516", "type": "raw_event" }, { "id": "c72961bd-22b2-4940-bca2-5c17e97faee1", "type": "raw_event" }, { "id": "3b955f74-7f88-4b00-8aa1-e952bb914172", "type": "raw_event" }, { "id": "702ddb53-81d3-426a-b582-ac1f6cc40135", "type": "raw_event" }, { "id": "26b396c1-b220-40d4-af89-9ae4f69c359d", "type": "raw_event" }, { "id": "b1f05846-e074-4bd1-8e7b-e2eee8683f00", "type": "raw_event" } ] } } }, { "id": "a1edd1e9-61b0-429c-a05a-31ac8d9d2b8b", "type": "port", "attributes": { "id": "a1edd1e9-61b0-429c-a05a-31ac8d9d2b8b", "name": "Vancouver", "code": "CAVAN", "state_abbr": "BC", "city": "Vancouver", "country_code": "CA", "latitude": "49.287489751", "longitude": "-123.094867064", "time_zone": "America/Los_Angeles" } }, { "id": "4c6c85eb-79bc-4f7c-ad66-962a6ab3a506", "type": "transport_event", "attributes": { "event": "container.transport.rail_loaded", "created_at": "2022-10-21T19:29:49Z", "voyage_number": null, "timestamp": "2022-10-21T18:11:00Z", "data_source": "shipping_line", "location_locode": "CAVAN", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "93921adf-af96-4096-9797-2abea7e95e79", "type": "shipment" } }, "container": { "data": { "id": "3be28cd9-165f-4af1-827a-902bef0147d0", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "a1edd1e9-61b0-429c-a05a-31ac8d9d2b8b", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.rail\_unloaded ```json theme={null} { "data": { "id": "c64aa704-adad-4a45-a2f1-0173afedc598", "type": "webhook_notification", "attributes": { "id": "c64aa704-adad-4a45-a2f1-0173afedc598", "event": "container.transport.rail_unloaded", "delivery_status": "pending", "created_at": "2022-10-21T20:18:00Z" }, "relationships": { "reference_object": { "data": { "id": "42a1cd6e-9891-401c-aa28-7e2dfcdf5895", "type": "transport_event" } }, "webhook": { "data": { "id": "99cd87c5-5bb2-49ba-96c8-a29f12159d82", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "0ee340ba-0f60-49cb-8ae1-551897887a52", "type": "shipment", "attributes": { "created_at": "2022-09-28T14:19:08Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "OOLU2706578920", "normalized_number": "2706578920", "shipping_line_scac": "OOLU", "shipping_line_name": "Orient Overseas Container Line", "shipping_line_short_name": "OOCL", "customer_name": "Schimmel-Beatty", "port_of_lading_locode": "TWKHH", "port_of_lading_name": "Kaohsiung", "port_of_discharge_locode": "USLGB", "port_of_discharge_name": "Long Beach", "pod_vessel_name": "COSCO ENGLAND", "pod_vessel_imo": "9516428", "pod_voyage_number": "054E", "destination_locode": "USEWI", "destination_name": "Elwood", "destination_timezone": "America/Chicago", "destination_ata_at": "2022-10-21T17:43:00Z", "destination_eta_at": "2022-10-18T09:36:00Z", "pol_etd_at": null, "pol_atd_at": "2022-09-27T02:05:00Z", "pol_timezone": "Asia/Taipei", "pod_eta_at": "2022-10-12T14:00:00Z", "pod_original_eta_at": "2022-10-10T15:00:00Z", "pod_ata_at": "2022-10-12T13:26:00Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:17:48Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "dbe43734-a6c0-40da-9dd8-955e3a536bcf", "type": "port" } }, "port_of_discharge": { "data": { "id": "52f2038f-aecd-4329-b368-a339ae81e4b7", "type": "port" } }, "pod_terminal": { "data": { "id": "6a1aa48d-1493-48ff-91c9-48ef6997e63b", "type": "terminal" } }, "destination": { "data": { "id": "43b40e7b-e339-450e-8581-19e49cb32a61", "type": "metro_area" } }, "destination_terminal": { "data": { "id": "9d04a5cb-083b-4a76-86a8-e37fc3dd65b3", "type": "rail_terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "7309bbe8-ec63-4740-979a-e4dc3047778a", "type": "container" } ] } }, "links": { "self": "/v2/shipments/7ffaff8a-8004-4c02-8acf-3d744708e0b4" } }, { "id": "7309bbe8-ec63-4740-979a-e4dc3047778a", "type": "container", "attributes": { "number": "OOLU6213464", "seal_number": null, "created_at": "2022-09-28T14:19:08Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-12T13:26:00Z", "pod_discharged_at": "2022-10-12T22:27:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ { "status": "hold", "name": "other", "description": "ONDOCK" }, { "status": "hold", "name": "other", "description": "CTF_CONTAINER_HOLD" }, { "status": "hold", "name": "freight", "description": "FREIGHT_BL_HOLD" } ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 56879, "pod_full_out_at": "2022-10-14T16:21:00Z", "empty_terminated_at": null, "terminal_checked_at": "2022-10-14T20:50:59Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "GROUNDED", "pod_last_tracking_request_at": "2022-10-14T20:50:59Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": "America/Chicago", "empty_terminated_timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "0ee340ba-0f60-49cb-8ae1-551897887a52", "type": "shipment" } }, "pod_terminal": { "data": { "id": "6a1aa48d-1493-48ff-91c9-48ef6997e63b", "type": "terminal" } }, "transport_events": { "data": [ { "id": "9ae17caa-9c9c-47a2-8444-949b25a4edc5", "type": "transport_event" }, { "id": "3313e5fd-f7f1-4bab-b1ca-4eefe26fa533", "type": "transport_event" }, { "id": "bd5a09a1-f77f-4b8a-9f0e-38a2ad30a26c", "type": "transport_event" }, { "id": "969da0e3-eb68-4da2-96e8-3765fc22a03f", "type": "transport_event" }, { "id": "707b092c-7662-4dc1-93c8-e8893c797da2", "type": "transport_event" }, { "id": "0de0c1d0-9502-4474-ad6f-acd138f7775d", "type": "transport_event" }, { "id": "09d00e28-8e4a-4362-aade-63ed7cb70968", "type": "transport_event" }, { "id": "b23ff291-e087-45e0-8dbf-141062a47d20", "type": "transport_event" }, { "id": "095aa809-3e1e-424d-9cd7-92d49a8f0f43", "type": "transport_event" }, { "id": "ba55a78a-7391-46bd-ad85-558b9c1fcbb5", "type": "transport_event" }, { "id": "6ca9d38f-1a8f-411a-87d8-af3f174999a1", "type": "transport_event" }, { "id": "3cf739f9-198a-409e-a9a8-89724eeb4821", "type": "transport_event" }, { "id": "18294c8a-a619-4416-a112-83dfde0e757c", "type": "transport_event" }, { "id": "d56f9846-95b5-4acb-87de-3c93fda143f1", "type": "transport_event" }, { "id": "42a1cd6e-9891-401c-aa28-7e2dfcdf5895", "type": "transport_event" }, { "id": "dd9edd7b-1798-4663-88bc-a5ce07700534", "type": "transport_event" }, { "id": "66643a7e-3e34-4693-8a6f-1d85126f93d1", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "4853f3bf-2660-430e-89d0-f1516dcd48f7", "type": "raw_event" }, { "id": "a7ade087-4e66-4555-bd3e-140dfb08785a", "type": "raw_event" }, { "id": "bdd42309-84db-4337-a80a-2ff3e417e95e", "type": "raw_event" }, { "id": "8e6203e7-f431-4cfa-af04-5a7a5018e745", "type": "raw_event" }, { "id": "a42b14f8-5a08-41ff-a864-8f92bbad4bb0", "type": "raw_event" }, { "id": "e92b5727-669e-4490-bab8-66d6edbd1f31", "type": "raw_event" }, { "id": "a98b1ae3-26be-4585-b8f2-c439c726b723", "type": "raw_event" }, { "id": "6d4cb7b5-32d4-4051-937b-5e5ad1dbbbad", "type": "raw_event" }, { "id": "489961d2-2791-45e8-baf3-d975a1dc0a01", "type": "raw_event" }, { "id": "16e55312-dd6d-4def-b4c2-39fb0eeaa3ac", "type": "raw_event" }, { "id": "596312ac-becf-4ed4-bc69-074d889385dc", "type": "raw_event" }, { "id": "1e314cb2-b9e7-4be5-a63a-d185588c3b41", "type": "raw_event" }, { "id": "150fc217-0bd5-427e-b09c-b123ec97ce2c", "type": "raw_event" }, { "id": "7feacaf8-62b8-47f4-abb4-d5ee8fdda43b", "type": "raw_event" }, { "id": "9435c083-5af6-47f3-90cf-8a554f995e10", "type": "raw_event" }, { "id": "2f451b22-9770-456f-b7fc-b050e42e37ce", "type": "raw_event" }, { "id": "c34c12c2-6bc3-44eb-a321-56b0a07233e4", "type": "raw_event" }, { "id": "ffa3d8b7-153d-4e2d-95c8-608cebfa8e6e", "type": "raw_event" }, { "id": "ae0f633f-c7f7-426b-8f9e-6112efe54b54", "type": "raw_event" }, { "id": "a7adde60-cf9e-41b9-a372-0410a3cfb437", "type": "raw_event" }, { "id": "67976eb0-e900-4c67-8dc5-327651625db4", "type": "raw_event" }, { "id": "84658720-b52f-43c6-8d8a-02c3c848b67f", "type": "raw_event" }, { "id": "a376f1f4-016b-40ba-83b6-514cd27a7c4b", "type": "raw_event" }, { "id": "7995ed60-cc48-44f2-b733-46094ca9e1d4", "type": "raw_event" }, { "id": "e1b66db7-d5a4-4b6b-8386-b4fc3dd56154", "type": "raw_event" }, { "id": "8950c6cf-6150-43cd-bf80-64bf776493de", "type": "raw_event" }, { "id": "aec9df81-c580-4c60-b1f8-15ff2cc2a293", "type": "raw_event" }, { "id": "25135e6c-3417-4de3-a0ba-9ca30aa768ed", "type": "raw_event" } ] } } }, { "id": "43b40e7b-e339-450e-8581-19e49cb32a61", "type": "metro_area", "attributes": { "id": "43b40e7b-e339-450e-8581-19e49cb32a61", "name": "Elwood", "state_abbr": "IL", "code": "USEWI", "latitude": "41.4039201", "longitude": "-88.1117242", "country_code": "US", "time_zone": "America/Chicago" } }, { "id": "9d04a5cb-083b-4a76-86a8-e37fc3dd65b3", "type": "rail_terminal", "attributes": { "id": "9d04a5cb-083b-4a76-86a8-e37fc3dd65b3", "nickname": "BNSF", "name": "BNSF - Logistics Park Chicago (LPC) Intermodal Facility", "city": "Elwood", "firms_code": "H572" }, "relationships": { "metro_area": { "data": { "id": "43b40e7b-e339-450e-8581-19e49cb32a61", "type": "metro_area" } }, "port": { "data": null } } }, { "id": "42a1cd6e-9891-401c-aa28-7e2dfcdf5895", "type": "transport_event", "attributes": { "event": "container.transport.rail_unloaded", "created_at": "2022-10-21T20:18:00Z", "voyage_number": null, "timestamp": "2022-10-21T18:32:00Z", "data_source": "shipping_line", "location_locode": "USEWI", "timezone": "America/Chicago" }, "relationships": { "shipment": { "data": { "id": "0ee340ba-0f60-49cb-8ae1-551897887a52", "type": "shipment" } }, "container": { "data": { "id": "7309bbe8-ec63-4740-979a-e4dc3047778a", "type": "container" } }, "vessel": { "data": null }, "location": { "data": { "id": "43b40e7b-e339-450e-8581-19e49cb32a61", "type": "metro_area" } }, "terminal": { "data": { "id": "9d04a5cb-083b-4a76-86a8-e37fc3dd65b3", "type": "rail_terminal" } } } } ] } ``` ## container.transport.transshipment\_arrived ```json theme={null} { "data": { "id": "8711bde5-8172-414b-b418-822c01ac8702", "type": "webhook_notification", "attributes": { "id": "8711bde5-8172-414b-b418-822c01ac8702", "event": "container.transport.transshipment_arrived", "delivery_status": "succeeded", "created_at": "2022-10-21T20:16:41Z" }, "relationships": { "reference_object": { "data": { "id": "a784ad6d-55e5-40ec-83d2-06bc12b4cbe6", "type": "transport_event" } }, "webhook": { "data": { "id": "441a3525-f2d7-4484-a46b-d89727cd3de6", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "9a86d383-af2e-4aaf-84ff-d868c4145de6", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "914595688", "normalized_number": "914595688", "shipping_line_scac": "SEAU", "shipping_line_name": "Sealand Americas", "shipping_line_short_name": "SeaLand Americas", "customer_name": "Runolfsson-Fisher", "port_of_lading_locode": "CLARI", "port_of_lading_name": "Arica", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "NORTHERN PRIORITY", "pod_vessel_imo": "9450313", "pod_voyage_number": "242N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-28T19:51:00Z", "pol_timezone": "America/Santiago", "pod_eta_at": "2022-10-27T12:00:00Z", "pod_original_eta_at": "2022-10-27T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "d49cd76a-8ee2-4b1e-90f7-ea75c008bbfb", "type": "port" } }, "port_of_discharge": { "data": { "id": "6dfceea1-86b1-426b-89e5-a20a4f134b58", "type": "port" } }, "pod_terminal": { "data": { "id": "c021339d-7145-429f-b713-9381c6874410", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "e68fc5f3-d058-47dd-935f-3b511b97f963", "type": "container" } ] } }, "links": { "self": "/v2/shipments/2de26519-3fb0-4748-b5ea-fca2b68dcab1" } }, { "id": "e68fc5f3-d058-47dd-935f-3b511b97f963", "type": "container", "attributes": { "number": "MNBU4188482", "seal_number": null, "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "9a86d383-af2e-4aaf-84ff-d868c4145de6", "type": "shipment" } }, "pod_terminal": { "data": { "id": "c021339d-7145-429f-b713-9381c6874410", "type": "terminal" } }, "transport_events": { "data": [ { "id": "48460e5e-109f-441e-85e5-f2dafdc0b580", "type": "transport_event" }, { "id": "a0b4028a-cd0d-4cee-81ec-fbcad0bbd6e4", "type": "transport_event" }, { "id": "cb7e6907-6f19-4993-9537-e5639f012855", "type": "transport_event" }, { "id": "28dce1a7-be9c-420b-9204-cb5ba1a8d9f5", "type": "transport_event" }, { "id": "a784ad6d-55e5-40ec-83d2-06bc12b4cbe6", "type": "transport_event" }, { "id": "8f90ebb0-e7ac-4dc3-8289-8d8d707cb599", "type": "transport_event" }, { "id": "e759a7c1-4698-43fa-8655-9e587cd543a0", "type": "transport_event" }, { "id": "3cc0cafb-1e9b-4cfa-8b36-bac8d0637bbc", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "686817d9-a55a-4ddb-a6c3-dbddc9da2c8d", "type": "raw_event" }, { "id": "a6fad72d-f691-4b39-bec9-1ad74f3ba00c", "type": "raw_event" }, { "id": "1debea05-bdef-40ed-afb1-85df593befb2", "type": "raw_event" }, { "id": "cb838330-54fe-4ae3-94d2-d6494a4553b4", "type": "raw_event" }, { "id": "d87dbb59-9b0c-4232-a04c-0b6b1400f865", "type": "raw_event" }, { "id": "d0d79af0-7bf0-4a87-b14b-219ae8d46a70", "type": "raw_event" }, { "id": "abe79851-1346-45a2-8134-60c2c20c82ad", "type": "raw_event" }, { "id": "eb2e1b88-570b-449b-a4c8-ec90f75221b0", "type": "raw_event" }, { "id": "1bbf2111-7125-4b56-877c-13eca65eec23", "type": "raw_event" }, { "id": "9c729bea-2e19-4bca-b6a4-a9112562ffd6", "type": "raw_event" }, { "id": "b75f1d15-375a-41a6-91cb-0055a7eb681e", "type": "raw_event" }, { "id": "e6fa1c43-f6a4-459a-840f-312e24257832", "type": "raw_event" }, { "id": "c4b19e31-309c-4454-9711-3adf028fca5e", "type": "raw_event" }, { "id": "150a808a-a9c4-4807-b3e6-21f0e74491ef", "type": "raw_event" } ] } } }, { "id": "b8047d9a-62de-4f10-b0d9-abc6ff025b67", "type": "port", "attributes": { "id": "b8047d9a-62de-4f10-b0d9-abc6ff025b67", "name": "Balboa", "code": "PABLB", "state_abbr": null, "city": null, "country_code": "PA", "latitude": "8.958933348", "longitude": "-79.565420224", "time_zone": "America/Panama" } }, { "id": "50ce561a-577f-46d1-af67-b236b847f51d", "type": "vessel", "attributes": { "name": "MERIDIAN", "imo": "7002605", "mmsi": "218415000", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "a784ad6d-55e5-40ec-83d2-06bc12b4cbe6", "type": "transport_event", "attributes": { "event": "container.transport.transshipment_arrived", "created_at": "2022-10-21T20:15:38Z", "voyage_number": "239N", "timestamp": "2022-10-11T13:01:00Z", "data_source": "shipping_line", "location_locode": "PABLB", "timezone": "America/Panama" }, "relationships": { "shipment": { "data": { "id": "9a86d383-af2e-4aaf-84ff-d868c4145de6", "type": "shipment" } }, "container": { "data": { "id": "e68fc5f3-d058-47dd-935f-3b511b97f963", "type": "container" } }, "vessel": { "data": { "id": "50ce561a-577f-46d1-af67-b236b847f51d", "type": "vessel" } }, "location": { "data": { "id": "b8047d9a-62de-4f10-b0d9-abc6ff025b67", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.transshipment\_departed ```json theme={null} { "data": { "id": "93006fa9-7ff4-49c3-ba69-4266aac3b54b", "type": "webhook_notification", "attributes": { "id": "93006fa9-7ff4-49c3-ba69-4266aac3b54b", "event": "container.transport.transshipment_departed", "delivery_status": "succeeded", "created_at": "2022-10-21T20:16:41Z" }, "relationships": { "reference_object": { "data": { "id": "e82e8530-1cf5-4680-9120-a737dde69083", "type": "transport_event" } }, "webhook": { "data": { "id": "1e6cd9f5-cb7e-43be-8a7e-99ebcd08106c", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "ccdf4809-0965-49c1-9dfb-9f4b250f3afd", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "914595688", "normalized_number": "914595688", "shipping_line_scac": "SEAU", "shipping_line_name": "Sealand Americas", "shipping_line_short_name": "SeaLand Americas", "customer_name": "Quigley, Romaguera and McDermott", "port_of_lading_locode": "CLARI", "port_of_lading_name": "Arica", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "NORTHERN PRIORITY", "pod_vessel_imo": "9450313", "pod_voyage_number": "242N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-28T19:51:00Z", "pol_timezone": "America/Santiago", "pod_eta_at": "2022-10-27T12:00:00Z", "pod_original_eta_at": "2022-10-27T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "6c07b6aa-7f5c-469a-8122-9509251e87c3", "type": "port" } }, "port_of_discharge": { "data": { "id": "9f951b96-5871-442d-a002-5e7b2b1bbb08", "type": "port" } }, "pod_terminal": { "data": { "id": "04f1344e-c5a2-43f1-9a20-7bf94258720b", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "a7a9790d-ec68-4afd-9063-a9cba0ec0cd9", "type": "container" } ] } }, "links": { "self": "/v2/shipments/2de26519-3fb0-4748-b5ea-fca2b68dcab1" } }, { "id": "a7a9790d-ec68-4afd-9063-a9cba0ec0cd9", "type": "container", "attributes": { "number": "MNBU4188482", "seal_number": null, "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "ccdf4809-0965-49c1-9dfb-9f4b250f3afd", "type": "shipment" } }, "pod_terminal": { "data": { "id": "04f1344e-c5a2-43f1-9a20-7bf94258720b", "type": "terminal" } }, "transport_events": { "data": [ { "id": "ca941257-104d-4556-881b-59a03ff27fa4", "type": "transport_event" }, { "id": "d17dd416-ee98-4a9b-9946-e053a246b79a", "type": "transport_event" }, { "id": "57aee521-0be4-4d8a-9b59-e90773371e46", "type": "transport_event" }, { "id": "8a3e98a1-ce78-4782-9173-55c2a457101e", "type": "transport_event" }, { "id": "4307eb90-b617-4b8e-8c5c-e9fa9f3b94d1", "type": "transport_event" }, { "id": "f4b2c3d6-1d6b-465a-ba59-c2b228683850", "type": "transport_event" }, { "id": "bdd4624d-5e59-4207-a03f-ee8ae00522aa", "type": "transport_event" }, { "id": "e82e8530-1cf5-4680-9120-a737dde69083", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "d87a8883-6ebc-402a-bf58-75837200b24e", "type": "raw_event" }, { "id": "08637455-91e6-4cb4-b68c-da7da5ce9eb0", "type": "raw_event" }, { "id": "bf9ea8d3-982e-4be6-aaaf-91a96c5081e2", "type": "raw_event" }, { "id": "b33f0ce7-0b01-4760-a61d-8792d1a5075d", "type": "raw_event" }, { "id": "dacc8b9e-95d9-4894-8ab2-a3172726b711", "type": "raw_event" }, { "id": "d1875e34-e862-44bf-8011-8f8e25d40222", "type": "raw_event" }, { "id": "9e5bf153-aa86-461e-bb7f-f75a44a4375c", "type": "raw_event" }, { "id": "c6fc7390-c634-44f2-b2a7-02c1397146f4", "type": "raw_event" }, { "id": "67cbee01-9731-4df4-b763-15ef0996abd8", "type": "raw_event" }, { "id": "dcc6745d-cb84-4575-9ecb-ea8017017289", "type": "raw_event" }, { "id": "798201b5-62f4-4d0b-951c-20d51960029b", "type": "raw_event" }, { "id": "a54fdf85-e96c-4bad-a993-f7ee0e857b9e", "type": "raw_event" }, { "id": "92b43e47-7af6-4317-bd1c-ee1dad0b6ab1", "type": "raw_event" }, { "id": "21c8fa3d-5702-4240-b9af-277d3853b441", "type": "raw_event" } ] } } }, { "id": "083870c7-a84c-4258-a033-73550322a336", "type": "port", "attributes": { "id": "083870c7-a84c-4258-a033-73550322a336", "name": "Manzanillo", "code": "PAMIT", "state_abbr": null, "city": null, "country_code": "PA", "latitude": "9.362360956", "longitude": "-79.882591837", "time_zone": "America/Panama" } }, { "id": "80750832-9ecf-4dae-b290-3263460fcbb1", "type": "vessel", "attributes": { "name": "NORTHERN PRIORITY", "imo": "9450313", "mmsi": "636091832", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "e82e8530-1cf5-4680-9120-a737dde69083", "type": "transport_event", "attributes": { "event": "container.transport.transshipment_departed", "created_at": "2022-10-21T20:15:39Z", "voyage_number": "242N", "timestamp": "2022-10-20T06:01:00Z", "data_source": "shipping_line", "location_locode": "PAMIT", "timezone": "America/Panama" }, "relationships": { "shipment": { "data": { "id": "ccdf4809-0965-49c1-9dfb-9f4b250f3afd", "type": "shipment" } }, "container": { "data": { "id": "a7a9790d-ec68-4afd-9063-a9cba0ec0cd9", "type": "container" } }, "vessel": { "data": { "id": "80750832-9ecf-4dae-b290-3263460fcbb1", "type": "vessel" } }, "location": { "data": { "id": "083870c7-a84c-4258-a033-73550322a336", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.transshipment\_discharged ```json theme={null} { "data": { "id": "a50e58c5-60eb-453e-b797-de590914d9c6", "type": "webhook_notification", "attributes": { "id": "a50e58c5-60eb-453e-b797-de590914d9c6", "event": "container.transport.transshipment_discharged", "delivery_status": "succeeded", "created_at": "2022-10-21T20:17:33Z" }, "relationships": { "reference_object": { "data": { "id": "2051adf7-b0d4-4f8c-9bb4-5cee4987d7a1", "type": "transport_event" } }, "webhook": { "data": { "id": "d1b29b83-d7f3-4a4a-be86-b3b2e359a021", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "eb2571f2-b189-4d84-ac49-6a606e1f3ce8", "type": "shipment", "attributes": { "created_at": "2022-10-13T06:24:29Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "6345849250", "normalized_number": "6345849250", "shipping_line_scac": "COSU", "shipping_line_name": "COSCO", "shipping_line_short_name": "COSCO", "customer_name": "Bruen, Orn and Ruecker", "port_of_lading_locode": "NOBVK", "port_of_lading_name": "Brevik", "port_of_discharge_locode": "IDJKT", "port_of_discharge_name": "Jakarta, Java", "pod_vessel_name": "CTP MAKASSAR", "pod_vessel_imo": "9181742", "pod_voyage_number": "446N", "destination_locode": null, "destination_name": "Jakarta,Indonesia", "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": "2022-12-05T14:00:00Z", "pol_etd_at": "2022-10-18T10:00:00Z", "pol_atd_at": "2022-10-18T22:12:00Z", "pol_timezone": "Europe/Oslo", "pod_eta_at": "2022-12-05T12:00:00Z", "pod_original_eta_at": "2022-11-28T12:00:00Z", "pod_ata_at": null, "pod_timezone": "Asia/Jakarta", "line_tracking_last_attempted_at": "2022-10-21T20:17:28Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "d4975962-efc1-47bf-9f94-b32b20645678", "type": "port" } }, "port_of_discharge": { "data": { "id": "c1a4b096-90fb-4c48-b797-1646af7a184d", "type": "port" } }, "pod_terminal": { "data": null }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "50959d84-85d4-47a0-a822-496383968eb5", "type": "container" }, { "id": "79f2bc77-8490-43c6-9938-b6ee1723388e", "type": "container" } ] } }, "links": { "self": "/v2/shipments/743450bd-e1e6-4c7c-8e82-5987a5aa578b" } }, { "id": "50959d84-85d4-47a0-a822-496383968eb5", "type": "container", "attributes": { "number": "OOLU1927772", "seal_number": "0167667", "created_at": "2022-10-13T06:24:29Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 20, "equipment_height": "standard", "weight_in_lbs": 59525, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "Asia/Jakarta", "final_destination_timezone": null, "empty_terminated_timezone": "Asia/Jakarta" }, "relationships": { "shipment": { "data": { "id": "eb2571f2-b189-4d84-ac49-6a606e1f3ce8", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "478eaae8-e93e-45d6-b7ff-868a9eeeae20", "type": "transport_event" }, { "id": "7c471ed0-98b5-4ab3-9e8b-732a5a54c65b", "type": "transport_event" }, { "id": "21c59959-0fcb-44cf-ba77-3a117c119c9c", "type": "transport_event" }, { "id": "55a4bbb5-cf7f-48e1-82fb-faa07be87580", "type": "transport_event" }, { "id": "2051adf7-b0d4-4f8c-9bb4-5cee4987d7a1", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "2dc91aa8-b9ae-43e3-bd7a-6092630d3c2e", "type": "raw_event" }, { "id": "681a2cab-337f-41aa-af4f-52b7c1a11e47", "type": "raw_event" }, { "id": "07452b4d-dead-4db6-973b-51cce89e9528", "type": "raw_event" }, { "id": "a8bca88f-61f6-4747-8e6c-a8e0b832733d", "type": "raw_event" }, { "id": "847e6c3f-bdde-47bd-b0d2-272381fdf327", "type": "raw_event" } ] } } }, { "id": "2a7f2058-e408-4259-baa9-ecf2c60ff275", "type": "port", "attributes": { "id": "2a7f2058-e408-4259-baa9-ecf2c60ff275", "name": "Rotterdam", "code": "NLRTM", "state_abbr": null, "city": null, "country_code": "NL", "latitude": "51.956693922", "longitude": "4.063456434", "time_zone": "Europe/Amsterdam" } }, { "id": "19f128eb-9be0-45de-8008-7d66dc7b0091", "type": "vessel", "attributes": { "name": "ELBSPRING", "imo": "9412529", "mmsi": "305575000", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "2051adf7-b0d4-4f8c-9bb4-5cee4987d7a1", "type": "transport_event", "attributes": { "event": "container.transport.transshipment_discharged", "created_at": "2022-10-21T20:17:33Z", "voyage_number": "50", "timestamp": "2022-10-21T16:00:00Z", "data_source": "shipping_line", "location_locode": "NLRTM", "timezone": "Europe/Amsterdam" }, "relationships": { "shipment": { "data": { "id": "eb2571f2-b189-4d84-ac49-6a606e1f3ce8", "type": "shipment" } }, "container": { "data": { "id": "50959d84-85d4-47a0-a822-496383968eb5", "type": "container" } }, "vessel": { "data": { "id": "19f128eb-9be0-45de-8008-7d66dc7b0091", "type": "vessel" } }, "location": { "data": { "id": "2a7f2058-e408-4259-baa9-ecf2c60ff275", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.transshipment\_loaded ```json theme={null} { "data": { "id": "e41c559a-3179-4e17-b739-d2458ff972a3", "type": "webhook_notification", "attributes": { "id": "e41c559a-3179-4e17-b739-d2458ff972a3", "event": "container.transport.transshipment_loaded", "delivery_status": "succeeded", "created_at": "2022-10-21T20:16:41Z" }, "relationships": { "reference_object": { "data": { "id": "abd25313-fc0f-4ad6-a9a0-5afdfe2116e2", "type": "transport_event" } }, "webhook": { "data": { "id": "f6e45855-97de-4c13-ba6c-ae2ee42f9d70", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "1e52ad99-2d0e-41ef-87ad-ea3572e2899e", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "914595688", "normalized_number": "914595688", "shipping_line_scac": "SEAU", "shipping_line_name": "Sealand Americas", "shipping_line_short_name": "SeaLand Americas", "customer_name": "Kozey, Ortiz and Legros", "port_of_lading_locode": "CLARI", "port_of_lading_name": "Arica", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "NORTHERN PRIORITY", "pod_vessel_imo": "9450313", "pod_voyage_number": "242N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-28T19:51:00Z", "pol_timezone": "America/Santiago", "pod_eta_at": "2022-10-27T12:00:00Z", "pod_original_eta_at": "2022-10-27T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "5a56e8c3-bac0-47da-99c6-cd83ab428a80", "type": "port" } }, "port_of_discharge": { "data": { "id": "990a5038-5273-4fe8-9a9f-4f1de2bcd418", "type": "port" } }, "pod_terminal": { "data": { "id": "62c6c1d7-757b-4cde-b189-9c6898d69be3", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "60998326-fb38-43c7-af7f-a0cc45825152", "type": "container" } ] } }, "links": { "self": "/v2/shipments/2de26519-3fb0-4748-b5ea-fca2b68dcab1" } }, { "id": "60998326-fb38-43c7-af7f-a0cc45825152", "type": "container", "attributes": { "number": "MNBU4188482", "seal_number": null, "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "1e52ad99-2d0e-41ef-87ad-ea3572e2899e", "type": "shipment" } }, "pod_terminal": { "data": { "id": "62c6c1d7-757b-4cde-b189-9c6898d69be3", "type": "terminal" } }, "transport_events": { "data": [ { "id": "0923b9f0-23aa-48b7-ba1c-a9069a6b18fe", "type": "transport_event" }, { "id": "b7926c0c-6d32-4952-8f45-93cf8b7be737", "type": "transport_event" }, { "id": "28c51b2e-22fb-4f92-a065-92cd5ec9a189", "type": "transport_event" }, { "id": "d21d539e-11fd-42c6-a9df-7b2d72f1efbe", "type": "transport_event" }, { "id": "3f8a6bc0-3fda-4a82-941a-5d75bf5f1dea", "type": "transport_event" }, { "id": "c42d173f-cebc-4caf-8c7d-ac11374aa3fc", "type": "transport_event" }, { "id": "abd25313-fc0f-4ad6-a9a0-5afdfe2116e2", "type": "transport_event" }, { "id": "ed8ee17c-276c-428a-a4c5-321ceb735293", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "742004b2-db59-4d68-8e94-35523d02b911", "type": "raw_event" }, { "id": "412d71b3-6314-4eb8-a2f7-9e582c5ec1b9", "type": "raw_event" }, { "id": "a03d1986-0889-4ba1-83a1-473209f026f5", "type": "raw_event" }, { "id": "f721632d-257a-4001-b8ab-9a66fff06bb8", "type": "raw_event" }, { "id": "fc0b6306-dcce-497f-b5e8-d4b445bc9ce7", "type": "raw_event" }, { "id": "de6dd640-9f81-4b8c-ba1a-95da3da1d415", "type": "raw_event" }, { "id": "7b60fd0f-d53e-47fd-a8df-d206df12ae30", "type": "raw_event" }, { "id": "1858d515-fa61-4a6c-979d-718b511304ff", "type": "raw_event" }, { "id": "28e25e0a-d57c-4294-8a96-b5f8e41777fa", "type": "raw_event" }, { "id": "4c003cd5-c1c6-4dbd-9a6a-8c7b98b0c176", "type": "raw_event" }, { "id": "b77b40c6-6df3-4324-ba58-6f11cfa430a7", "type": "raw_event" }, { "id": "6aa41832-c607-40fb-924b-8f7017cbbb1b", "type": "raw_event" }, { "id": "da1617cf-1557-4766-bd1c-6c60bc32db87", "type": "raw_event" }, { "id": "26dcb356-a6e4-4255-bc29-a1b074cfb8f0", "type": "raw_event" } ] } } }, { "id": "928f91f5-74d0-4a65-b5cf-995a4a026770", "type": "port", "attributes": { "id": "928f91f5-74d0-4a65-b5cf-995a4a026770", "name": "Manzanillo", "code": "PAMIT", "state_abbr": null, "city": null, "country_code": "PA", "latitude": "9.362360956", "longitude": "-79.882591837", "time_zone": "America/Panama" } }, { "id": "2327b55c-4abb-410d-b97f-dcddf4734f89", "type": "vessel", "attributes": { "name": "NORTHERN PRIORITY", "imo": "9450313", "mmsi": "636091832", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "abd25313-fc0f-4ad6-a9a0-5afdfe2116e2", "type": "transport_event", "attributes": { "event": "container.transport.transshipment_loaded", "created_at": "2022-10-21T20:15:38Z", "voyage_number": "242N", "timestamp": "2022-10-19T18:09:00Z", "data_source": "shipping_line", "location_locode": "PAMIT", "timezone": "America/Panama" }, "relationships": { "shipment": { "data": { "id": "1e52ad99-2d0e-41ef-87ad-ea3572e2899e", "type": "shipment" } }, "container": { "data": { "id": "60998326-fb38-43c7-af7f-a0cc45825152", "type": "container" } }, "vessel": { "data": { "id": "2327b55c-4abb-410d-b97f-dcddf4734f89", "type": "vessel" } }, "location": { "data": { "id": "928f91f5-74d0-4a65-b5cf-995a4a026770", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.vessel\_arrived ```json theme={null} { "data": { "id": "be283e7f-6d95-4d87-b8cc-e4a88a0738ac", "type": "webhook_notification", "attributes": { "id": "be283e7f-6d95-4d87-b8cc-e4a88a0738ac", "event": "container.transport.vessel_arrived", "delivery_status": "succeeded", "created_at": "2022-10-21T20:15:39Z" }, "relationships": { "reference_object": { "data": { "id": "3e814da7-53fe-4397-9776-c97e248eda91", "type": "transport_event" } }, "webhook": { "data": { "id": "361830fa-b087-47f2-94b0-06af1ac5d2a8", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "e55680a0-3378-428e-9783-7d72f9c3fc7f", "type": "shipment", "attributes": { "created_at": "2022-09-09T12:05:57Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "ZIMULEH9024455", "normalized_number": "ZIMULEH9024455", "shipping_line_scac": "ZIMU", "shipping_line_name": "Zim American Integrated Shipping Services", "shipping_line_short_name": "Zim Line", "customer_name": "Denesik, Senger and Feil", "port_of_lading_locode": "FRLEH", "port_of_lading_name": "Le Havre", "port_of_discharge_locode": "INNSA", "port_of_discharge_name": "Nhava Sheva", "pod_vessel_name": "TONGALA", "pod_vessel_imo": "9278105", "pod_voyage_number": "132/E", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": "2022-09-28T22:00:00Z", "pol_atd_at": "2022-09-28T13:40:00Z", "pol_timezone": "Europe/Paris", "pod_eta_at": "2022-10-20T18:30:00Z", "pod_original_eta_at": "2022-10-13T18:30:00Z", "pod_ata_at": "2022-10-21T15:53:00Z", "pod_timezone": "Asia/Calcutta", "line_tracking_last_attempted_at": "2022-10-21T19:32:09Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "b9e91f35-d472-48a8-912d-dbb1f85fe38e", "type": "port" } }, "port_of_discharge": { "data": { "id": "be2b403c-ebaa-4125-aebd-3471ec765edf", "type": "port" } }, "pod_terminal": { "data": null }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "5c3e90ed-5c8c-4c01-a0ce-ea544a2a9f6d", "type": "container" } ] } }, "links": { "self": "/v2/shipments/ae598754-a193-4a1f-9a4e-483d78b48d8c" } }, { "id": "5c3e90ed-5c8c-4c01-a0ce-ea544a2a9f6d", "type": "container", "attributes": { "number": "CAIU3758064", "seal_number": null, "created_at": "2022-09-09T12:05:58Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-21T15:53:00Z", "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 20, "equipment_height": "standard", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "Asia/Calcutta", "final_destination_timezone": null, "empty_terminated_timezone": "Asia/Calcutta" }, "relationships": { "shipment": { "data": { "id": "e55680a0-3378-428e-9783-7d72f9c3fc7f", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "2f50d744-8c94-4d2c-9a84-857b7871010f", "type": "transport_event" }, { "id": "58fa4da4-e265-45f2-aa47-63596834d094", "type": "transport_event" }, { "id": "3e814da7-53fe-4397-9776-c97e248eda91", "type": "transport_event" }, { "id": "218d96b8-01e8-4349-852a-b03e05182d56", "type": "transport_event" }, { "id": "1a74d4d0-d24c-47c9-8818-59ae75562c8f", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "e96fa9f3-b83b-4340-9853-ca7f793c0ee9", "type": "raw_event" }, { "id": "9d652d24-2753-4b36-b267-c456dee0ce7f", "type": "raw_event" }, { "id": "b06b1ad9-c029-435c-99a0-e2dc6e7121c3", "type": "raw_event" }, { "id": "89aa1a6d-3bb4-477e-a4e3-b8ee9be02b35", "type": "raw_event" }, { "id": "c4b65cc1-7def-46f7-b9e4-35a22d1a58a5", "type": "raw_event" } ] } } }, { "id": "be2b403c-ebaa-4125-aebd-3471ec765edf", "type": "port", "attributes": { "id": "be2b403c-ebaa-4125-aebd-3471ec765edf", "name": "Nhava Sheva", "code": "INNSA", "state_abbr": null, "city": null, "country_code": "IN", "latitude": "18.95580615", "longitude": "72.951204698", "time_zone": "Asia/Calcutta" } }, { "id": "e55637e2-3fd7-405e-b987-401c1c880905", "type": "vessel", "attributes": { "name": "TONGALA", "imo": "9278105", "mmsi": "636013644", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "3e814da7-53fe-4397-9776-c97e248eda91", "type": "transport_event", "attributes": { "event": "container.transport.vessel_arrived", "created_at": "2022-10-21T20:15:39Z", "voyage_number": "132/E", "timestamp": "2022-10-21T15:53:00Z", "data_source": "shipping_line", "location_locode": "INNSA", "timezone": "Asia/Calcutta" }, "relationships": { "shipment": { "data": { "id": "e55680a0-3378-428e-9783-7d72f9c3fc7f", "type": "shipment" } }, "container": { "data": { "id": "5c3e90ed-5c8c-4c01-a0ce-ea544a2a9f6d", "type": "container" } }, "vessel": { "data": { "id": "e55637e2-3fd7-405e-b987-401c1c880905", "type": "vessel" } }, "location": { "data": { "id": "be2b403c-ebaa-4125-aebd-3471ec765edf", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.vessel\_berthed ```json theme={null} { "data": { "id": "4c2bee7b-5929-4a8d-baa4-b8f8580597be", "type": "webhook_notification", "attributes": { "id": "4c2bee7b-5929-4a8d-baa4-b8f8580597be", "event": "container.transport.vessel_berthed", "delivery_status": "succeeded", "created_at": "2022-10-21T18:52:26Z" }, "relationships": { "reference_object": { "data": { "id": "6242e7d4-eeea-40ec-af56-fc0a71e2a36b", "type": "transport_event" } }, "webhook": { "data": { "id": "9ed8cc42-5b0e-4ffc-96a6-335e96cdfcba", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "f028a4c5-4c0b-4894-b4b2-4919d266737e", "type": "shipment", "attributes": { "created_at": "2022-09-22T08:25:55Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "HDMUXMNM78424800", "normalized_number": "XMNM78424800", "shipping_line_scac": "HDMU", "shipping_line_name": "Hyundai Merchant Marine", "shipping_line_short_name": "Hyundai", "customer_name": "Kuvalis-Paucek", "port_of_lading_locode": "CNXMN", "port_of_lading_name": "Xiamen", "port_of_discharge_locode": "USLAX", "port_of_discharge_name": "Los Angeles", "pod_vessel_name": "YM UNANIMITY", "pod_vessel_imo": "9462718", "pod_voyage_number": "0063E", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": "2022-09-27T22:00:00Z", "pol_atd_at": "2022-09-28T02:30:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-10-17T13:00:00Z", "pod_original_eta_at": "2022-10-15T15:00:00Z", "pod_ata_at": "2022-10-18T17:35:17Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T18:52:23Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "5d392f9e-e3af-41d2-b7cf-7c8e48b5277d", "type": "port" } }, "port_of_discharge": { "data": { "id": "214edbe5-f438-4492-bb18-3cd053c92cc7", "type": "port" } }, "pod_terminal": { "data": { "id": "b76896e1-fb93-4ebe-bbb2-d9e7eefc7553", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "82052525-07c1-4c45-9a09-e7633cbab373", "type": "container" } ] } }, "links": { "self": "/v2/shipments/a065301b-0205-496a-a317-ef0abd2ae2e3" } }, { "id": "82052525-07c1-4c45-9a09-e7633cbab373", "type": "container", "attributes": { "number": "GAOU6337366", "seal_number": "", "created_at": "2022-09-22T08:25:55Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-17T13:00:00Z", "pod_discharged_at": "2022-10-18T17:21:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": true, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 0, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T19:44:09Z", "fees_at_pod_terminal": [ ], "pickup_lfd": "2022-10-24T07:00:00Z", "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "In Yard
(Decked)", "pod_last_tracking_request_at": "2022-10-21T19:44:09Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "f028a4c5-4c0b-4894-b4b2-4919d266737e", "type": "shipment" } }, "pod_terminal": { "data": { "id": "b76896e1-fb93-4ebe-bbb2-d9e7eefc7553", "type": "terminal" } }, "transport_events": { "data": [ { "id": "82abbf20-17da-43ce-b62e-a94f0dbc51ad", "type": "transport_event" }, { "id": "75641949-c9b1-4726-b9dd-58577f3c0709", "type": "transport_event" }, { "id": "89deda0c-ff71-4e87-988e-cdb96f1af4b2", "type": "transport_event" }, { "id": "2553a3b5-e41f-4e22-9798-1aab7f275d35", "type": "transport_event" }, { "id": "6242e7d4-eeea-40ec-af56-fc0a71e2a36b", "type": "transport_event" }, { "id": "04fb0c48-fa3a-42e2-af35-0bec1d09f141", "type": "transport_event" }, { "id": "c45fe70b-83bf-46dd-ba5a-db03002ba349", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "ccb3e789-3902-469f-bbab-96a1ede50dd8", "type": "raw_event" }, { "id": "231b3fbe-6d33-4386-8258-1356ee9b9518", "type": "raw_event" }, { "id": "5d83c231-c711-42a0-abfc-6fedb259381f", "type": "raw_event" }, { "id": "a23c7de8-2ae0-4ca6-9c54-97d905d11a58", "type": "raw_event" }, { "id": "9e6700a1-15cd-4010-b8fc-799de9e3b1a5", "type": "raw_event" }, { "id": "8e50b041-1f9c-40bf-ab78-588e69bc4311", "type": "raw_event" }, { "id": "8027c3fc-c55c-4cb0-98de-ecfb2c8aa0ad", "type": "raw_event" } ] } } }, { "id": "214edbe5-f438-4492-bb18-3cd053c92cc7", "type": "port", "attributes": { "id": "214edbe5-f438-4492-bb18-3cd053c92cc7", "name": "Los Angeles", "code": "USLAX", "state_abbr": "CA", "city": "Los Angeles", "country_code": "US", "latitude": "33.728193631", "longitude": "-118.255820307", "time_zone": "America/Los_Angeles" } }, { "id": "b76896e1-fb93-4ebe-bbb2-d9e7eefc7553", "type": "terminal", "attributes": { "id": "b76896e1-fb93-4ebe-bbb2-d9e7eefc7553", "nickname": "WBCT", "name": "West Basin Container Terminal", "firms_code": "Y773", "smdg_code": null, "bic_facility_code": null, "provided_data": { "pickup_lfd": false, "pickup_lfd_notes": "", "available_for_pickup": false, "fees_at_pod_terminal": false, "holds_at_pod_terminal": false, "pickup_appointment_at": false, "location_at_pod_terminal": false, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": false, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "701 New Dock Street Berths 212-225", "city": "Terminal Island", "state": "California", "state_abbr": "CA", "zip": "90731", "country": "United States" }, "relationships": { "port": { "data": { "id": "214edbe5-f438-4492-bb18-3cd053c92cc7", "type": "port" } } } }, { "id": "f800df08-186c-40b9-8d3c-3fcc0838cbe6", "type": "vessel", "attributes": { "name": "YM UNANIMITY", "imo": "9462718", "mmsi": "416466000", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 25, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "6242e7d4-eeea-40ec-af56-fc0a71e2a36b", "type": "transport_event", "attributes": { "event": "container.transport.vessel_berthed", "created_at": "2022-10-21T18:52:26Z", "voyage_number": "0063E", "timestamp": "2022-10-17T13:00:00Z", "data_source": "shipping_line", "location_locode": "USLAX", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "f028a4c5-4c0b-4894-b4b2-4919d266737e", "type": "shipment" } }, "container": { "data": { "id": "82052525-07c1-4c45-9a09-e7633cbab373", "type": "container" } }, "vessel": { "data": { "id": "f800df08-186c-40b9-8d3c-3fcc0838cbe6", "type": "vessel" } }, "location": { "data": { "id": "214edbe5-f438-4492-bb18-3cd053c92cc7", "type": "port" } }, "terminal": { "data": { "id": "b76896e1-fb93-4ebe-bbb2-d9e7eefc7553", "type": "terminal" } } } } ] } ``` ## container.transport.vessel\_departed ```json theme={null} { "data": { "id": "f65f7fff-2384-4f90-919b-b716c16bc670", "type": "webhook_notification", "attributes": { "id": "f65f7fff-2384-4f90-919b-b716c16bc670", "event": "container.transport.vessel_departed", "delivery_status": "succeeded", "created_at": "2022-10-21T20:16:41Z" }, "relationships": { "reference_object": { "data": { "id": "2b8eb6b3-6dcb-4acc-a234-dfc971408762", "type": "transport_event" } }, "webhook": { "data": { "id": "501aae38-e752-4f15-ab6e-73ea0ede3ca2", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "a65a7f43-0038-4f60-acff-c97a4979d323", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "914595688", "normalized_number": "914595688", "shipping_line_scac": "SEAU", "shipping_line_name": "Sealand Americas", "shipping_line_short_name": "SeaLand Americas", "customer_name": "Lang and Sons", "port_of_lading_locode": "CLARI", "port_of_lading_name": "Arica", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "NORTHERN PRIORITY", "pod_vessel_imo": "9450313", "pod_voyage_number": "242N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-28T19:51:00Z", "pol_timezone": "America/Santiago", "pod_eta_at": "2022-10-27T12:00:00Z", "pod_original_eta_at": "2022-10-27T12:00:00Z", "pod_ata_at": null, "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "cbf247a7-a86c-491f-948e-6a95a41e9199", "type": "port" } }, "port_of_discharge": { "data": { "id": "e06c809e-c437-47ac-92a1-aeb1c6f14480", "type": "port" } }, "pod_terminal": { "data": { "id": "a01b7de4-05a5-4871-8074-c524057216ec", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "56ad45c8-dbd0-4c1e-bee7-7c4376db3924", "type": "container" } ] } }, "links": { "self": "/v2/shipments/2de26519-3fb0-4748-b5ea-fca2b68dcab1" } }, { "id": "56ad45c8-dbd0-4c1e-bee7-7c4376db3924", "type": "container", "attributes": { "number": "MNBU4188482", "seal_number": null, "created_at": "2022-10-21T20:15:38Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "reefer", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "a65a7f43-0038-4f60-acff-c97a4979d323", "type": "shipment" } }, "pod_terminal": { "data": { "id": "a01b7de4-05a5-4871-8074-c524057216ec", "type": "terminal" } }, "transport_events": { "data": [ { "id": "875a1706-b8cd-4a27-9b0d-b6bc76b01a91", "type": "transport_event" }, { "id": "571209fb-d43e-4361-8bc6-f17a72005964", "type": "transport_event" }, { "id": "2b8eb6b3-6dcb-4acc-a234-dfc971408762", "type": "transport_event" }, { "id": "7d77608f-647c-45a3-9308-12d988d5be62", "type": "transport_event" }, { "id": "74c00224-82e2-4bb8-aa2a-291aa4f5554d", "type": "transport_event" }, { "id": "1580e710-6e00-4e7c-b0e4-cabed65d09e3", "type": "transport_event" }, { "id": "efa9723b-fb8d-4add-8059-8a95bcb78cba", "type": "transport_event" }, { "id": "3a19cba1-a2e8-40e9-b9cb-8cadbe802ca9", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "f4bf9733-cfef-4e01-ad8c-efc874dd4b83", "type": "raw_event" }, { "id": "29f37e62-08a5-45c5-87dd-eee6a8cddc9c", "type": "raw_event" }, { "id": "c692006a-0755-4f0f-8b6f-e22360de589e", "type": "raw_event" }, { "id": "b41de73f-aa1d-473e-8fed-9bf9ba6f5384", "type": "raw_event" }, { "id": "2c60b856-6120-44ba-8c7f-a8e0a7dc3306", "type": "raw_event" }, { "id": "3d13f46c-b04a-435e-9bc9-7d4c2fb70fe4", "type": "raw_event" }, { "id": "00104149-7bfd-4d11-989a-0bcf3089f446", "type": "raw_event" }, { "id": "5a224d3b-d3b7-489a-a776-09f053e422b1", "type": "raw_event" }, { "id": "85cfe2ce-c88e-4b55-b25f-f36a0c3f5e6a", "type": "raw_event" }, { "id": "b4481a38-511b-4d84-b92c-e36b6e050b5c", "type": "raw_event" }, { "id": "527e2d94-93e2-40f8-9421-a80fd53e2fe8", "type": "raw_event" }, { "id": "86666d95-cb85-4106-b68c-816702e851bf", "type": "raw_event" }, { "id": "afe2b57f-5363-4ad9-ad0e-a83c8928c0d9", "type": "raw_event" }, { "id": "e1240511-7a64-49f7-8dc1-bdf31848f1a7", "type": "raw_event" } ] } } }, { "id": "cbf247a7-a86c-491f-948e-6a95a41e9199", "type": "port", "attributes": { "id": "cbf247a7-a86c-491f-948e-6a95a41e9199", "name": "Arica", "code": "CLARI", "state_abbr": null, "city": null, "country_code": "CL", "latitude": "-18.471872947", "longitude": "-70.327958963", "time_zone": "America/Santiago" } }, { "id": "95016ff7-1084-416a-9c85-4af24e91d883", "type": "vessel", "attributes": { "name": "MERIDIAN", "imo": "7002605", "mmsi": "218415000", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 44, "navigational_heading_degrees": 1, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "2b8eb6b3-6dcb-4acc-a234-dfc971408762", "type": "transport_event", "attributes": { "event": "container.transport.vessel_departed", "created_at": "2022-10-21T20:15:38Z", "voyage_number": "239N", "timestamp": "2022-09-28T19:51:00Z", "data_source": "shipping_line", "location_locode": "CLARI", "timezone": "America/Santiago" }, "relationships": { "shipment": { "data": { "id": "a65a7f43-0038-4f60-acff-c97a4979d323", "type": "shipment" } }, "container": { "data": { "id": "56ad45c8-dbd0-4c1e-bee7-7c4376db3924", "type": "container" } }, "vessel": { "data": { "id": "95016ff7-1084-416a-9c85-4af24e91d883", "type": "vessel" } }, "location": { "data": { "id": "cbf247a7-a86c-491f-948e-6a95a41e9199", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.transport.vessel\_discharged ```json theme={null} { "data": { "id": "5c048ec8-afb0-48ca-8657-fa262dc9bbd7", "type": "webhook_notification", "attributes": { "id": "5c048ec8-afb0-48ca-8657-fa262dc9bbd7", "event": "container.transport.vessel_discharged", "delivery_status": "succeeded", "created_at": "2022-10-21T20:14:17Z" }, "relationships": { "reference_object": { "data": { "id": "d637c864-ef35-4df1-9563-ba8bbb179af5", "type": "transport_event" } }, "webhook": { "data": { "id": "851d3a8d-4f95-4296-be6d-0510ece0376d", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "56c8b2c7-a5e0-4c51-9793-f7dadc1fa52c", "type": "shipment", "attributes": { "created_at": "2022-09-01T15:22:22Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "TA2PTC560500", "normalized_number": "TA2PTC560500", "shipping_line_scac": "ONEY", "shipping_line_name": "Ocean Network Express", "shipping_line_short_name": "ONE", "customer_name": "Schaden and Sons", "port_of_lading_locode": "CNQIN", "port_of_lading_name": "Qingdao", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "ESSEN EXPRESS", "pod_vessel_imo": "9501370", "pod_voyage_number": "042E", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-07-30T12:24:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-09-22T15:00:00Z", "pod_original_eta_at": "2022-09-23T10:00:00Z", "pod_ata_at": "2022-10-19T19:55:00Z", "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T20:14:12Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "25a0e8eb-a957-4973-a8fd-e984552baafa", "type": "port" } }, "port_of_discharge": { "data": { "id": "27f76ae6-d6d9-4938-878b-7113cd628159", "type": "port" } }, "pod_terminal": { "data": { "id": "ad02bb7c-a8a3-4ec5-bbb9-220f3dbf797d", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "7e9be7ac-2845-4130-b032-fb447d3c3126", "type": "container" } ] } }, "links": { "self": "/v2/shipments/44ddc574-6636-44f0-be9f-6dd6a7e5f0fb" } }, { "id": "7e9be7ac-2845-4130-b032-fb447d3c3126", "type": "container", "attributes": { "number": "NYKU0800893", "seal_number": "CND674488", "created_at": "2022-09-01T15:22:23Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-19T19:55:00Z", "pod_discharged_at": "2022-10-21T15:19:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": true, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 18928, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T19:45:07Z", "fees_at_pod_terminal": [ ], "pickup_lfd": "2022-10-27T04:00:00Z", "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "In Yard", "pod_last_tracking_request_at": "2022-10-21T19:45:07Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "56c8b2c7-a5e0-4c51-9793-f7dadc1fa52c", "type": "shipment" } }, "pod_terminal": { "data": { "id": "ad02bb7c-a8a3-4ec5-bbb9-220f3dbf797d", "type": "terminal" } }, "transport_events": { "data": [ { "id": "81879bc8-3b1e-44e7-8b82-18747c5a55c1", "type": "transport_event" }, { "id": "400895bd-70b7-4ef7-8fef-8edd63eb1450", "type": "transport_event" }, { "id": "b2d26b74-3189-410e-a4e6-344e2a5ecbc9", "type": "transport_event" }, { "id": "90e32553-9d25-4426-b625-128d26f9f9c5", "type": "transport_event" }, { "id": "72375da8-6916-4db4-80a5-903602035b91", "type": "transport_event" }, { "id": "a0718da3-3185-4038-9b12-fc1886895933", "type": "transport_event" }, { "id": "eb452da3-ad22-457b-b3b5-6ef7d691efef", "type": "transport_event" }, { "id": "e474a621-fdad-413b-8a86-80ca59444d2e", "type": "transport_event" }, { "id": "9f274f93-4763-4af3-a513-47be9de6db74", "type": "transport_event" }, { "id": "c9a093b5-8962-4e67-9c65-cc82811352ae", "type": "transport_event" }, { "id": "d637c864-ef35-4df1-9563-ba8bbb179af5", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "4d66e330-b0b0-47bc-bd67-1385b6da145f", "type": "raw_event" }, { "id": "7db280b7-5728-4d5c-a3f0-80086e726144", "type": "raw_event" }, { "id": "93cbaa5e-67c8-4aa0-b264-aed51f0a25eb", "type": "raw_event" }, { "id": "88a6cf44-d652-4b0b-b58e-2e2d5ead3cf0", "type": "raw_event" }, { "id": "9583e9f1-70c0-426b-801a-99f9193cb7a4", "type": "raw_event" }, { "id": "e6663d02-6b90-4d4f-a697-1980eca44789", "type": "raw_event" }, { "id": "d6ad787d-6ad1-479c-87f6-2e104d1275ef", "type": "raw_event" }, { "id": "6a227c8f-865f-47be-8551-f043be9b9a8b", "type": "raw_event" }, { "id": "0b6ea128-508c-4951-9c08-a33ba5134447", "type": "raw_event" }, { "id": "614b23d9-0b23-4800-b5fe-ac2d06178eb3", "type": "raw_event" }, { "id": "d83e119a-9214-4e07-ae13-024c68b3d231", "type": "raw_event" }, { "id": "7ea41e5c-b6dd-4972-a42b-e630cbaaa6da", "type": "raw_event" }, { "id": "12c1202e-5a6b-4551-a78e-670c52dde93a", "type": "raw_event" }, { "id": "fbff6533-b387-4af5-912b-4040ba3d5a34", "type": "raw_event" } ] } } }, { "id": "27f76ae6-d6d9-4938-878b-7113cd628159", "type": "port", "attributes": { "id": "27f76ae6-d6d9-4938-878b-7113cd628159", "name": "New York / New Jersey", "code": "USNYC", "state_abbr": "NY", "city": "New York", "country_code": "US", "latitude": "40.684996498", "longitude": "-74.151115685", "time_zone": "America/New_York" } }, { "id": "ad02bb7c-a8a3-4ec5-bbb9-220f3dbf797d", "type": "terminal", "attributes": { "id": "ad02bb7c-a8a3-4ec5-bbb9-220f3dbf797d", "nickname": "GCTB", "name": "GCT Bayonne", "firms_code": "E364", "smdg_code": null, "bic_facility_code": null, "provided_data": { "pickup_lfd": false, "pickup_lfd_notes": "", "available_for_pickup": false, "fees_at_pod_terminal": false, "holds_at_pod_terminal": false, "pickup_appointment_at": false, "location_at_pod_terminal": false, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": false, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "701 New Dock Street Berths 212-225", "city": "Terminal Island", "state": "California", "state_abbr": "CA", "zip": "90731", "country": "United States" }, "relationships": { "port": { "data": { "id": "27f76ae6-d6d9-4938-878b-7113cd628159", "type": "port" } } } }, { "id": "043bbbbe-c26f-44fb-a21c-4ee80c8fe319", "type": "vessel", "attributes": { "name": "ESSEN EXPRESS", "imo": "9501370", "mmsi": "218474000", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 13, "navigational_heading_degrees": 99, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "d637c864-ef35-4df1-9563-ba8bbb179af5", "type": "transport_event", "attributes": { "event": "container.transport.vessel_discharged", "created_at": "2022-10-21T20:14:17Z", "voyage_number": "042E", "timestamp": "2022-10-21T15:19:00Z", "data_source": "shipping_line", "location_locode": "USNYC", "timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "56c8b2c7-a5e0-4c51-9793-f7dadc1fa52c", "type": "shipment" } }, "container": { "data": { "id": "7e9be7ac-2845-4130-b032-fb447d3c3126", "type": "container" } }, "vessel": { "data": { "id": "043bbbbe-c26f-44fb-a21c-4ee80c8fe319", "type": "vessel" } }, "location": { "data": { "id": "27f76ae6-d6d9-4938-878b-7113cd628159", "type": "port" } }, "terminal": { "data": { "id": "ad02bb7c-a8a3-4ec5-bbb9-220f3dbf797d", "type": "terminal" } } } } ] } ``` ## container.transport.vessel\_loaded ```json theme={null} { "data": { "id": "a3baf7bb-3ffe-485e-bf9d-7b7dd17a08a8", "type": "webhook_notification", "attributes": { "id": "a3baf7bb-3ffe-485e-bf9d-7b7dd17a08a8", "event": "container.transport.vessel_loaded", "delivery_status": "succeeded", "created_at": "2022-10-21T20:16:47Z" }, "relationships": { "reference_object": { "data": { "id": "58114b8d-7aab-491d-97ce-7b32c0c1d198", "type": "transport_event" } }, "webhook": { "data": { "id": "7c353e67-cab6-422e-a17f-8483bf250dd9", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "2bae2c8b-c682-47a6-81c7-f1ac9d4404ef", "type": "shipment", "attributes": { "created_at": "2022-10-18T23:20:40Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "HDMUNBOZ32457200", "normalized_number": "NBOZ32457200", "shipping_line_scac": "HDMU", "shipping_line_name": "Hyundai Merchant Marine", "shipping_line_short_name": "Hyundai", "customer_name": "Roberts LLC", "port_of_lading_locode": "CNNGB", "port_of_lading_name": "Ningbo", "port_of_discharge_locode": "USLAX", "port_of_discharge_name": "Los Angeles", "pod_vessel_name": "NYK THEMIS", "pod_vessel_imo": "9356696", "pod_voyage_number": "0082E", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-23T00:30:00Z", "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-10-22T12:30:00Z", "pod_original_eta_at": "2022-10-22T12:30:00Z", "pod_ata_at": null, "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:13:02Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "b80acdc3-e2e7-4d09-8c7a-48ce12b4dd38", "type": "port" } }, "port_of_discharge": { "data": { "id": "5d0f3e26-a5a7-4aff-a73f-2eacb3ca0a05", "type": "port" } }, "pod_terminal": { "data": { "id": "43cf9fea-eb03-428a-8e57-6da700f95adc", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "e7fd77a6-5b1d-49c6-8790-9597e154c3c6", "type": "container" }, { "id": "d1a33088-16fa-475c-9ea4-d5098ae9b8df", "type": "container" }, { "id": "c7876dc6-ccad-4219-b0a2-1e9e9845f474", "type": "container" }, { "id": "9bbff5af-73fa-463e-b715-d2f6c01c58cc", "type": "container" }, { "id": "e637137f-ad05-41e3-9a50-045d365d96d9", "type": "container" }, { "id": "8e4f2995-a25a-4c6c-9382-3c02ce1288af", "type": "container" }, { "id": "a5970c64-61c2-4f13-b16d-de46871b77f0", "type": "container" } ] } }, "links": { "self": "/v2/shipments/35285253-d023-4c08-ab12-4ea7ee7793cf" } }, { "id": "c7876dc6-ccad-4219-b0a2-1e9e9845f474", "type": "container", "attributes": { "number": "KOCU4221161", "seal_number": "211962498", "created_at": "2022-10-18T23:20:40Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "high_cube", "weight_in_lbs": 20119, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T20:09:50Z", "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": "On-Board Vessel", "pod_last_tracking_request_at": "2022-10-21T20:09:50Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "2bae2c8b-c682-47a6-81c7-f1ac9d4404ef", "type": "shipment" } }, "pod_terminal": { "data": { "id": "43cf9fea-eb03-428a-8e57-6da700f95adc", "type": "terminal" } }, "transport_events": { "data": [ { "id": "e39a063e-da6b-4b97-bb7a-bf27b1b2d96e", "type": "transport_event" }, { "id": "58e026b4-4252-4f40-910e-416b75e3f656", "type": "transport_event" }, { "id": "2032b8a4-150d-40c1-a4d2-9dc89606ba9b", "type": "transport_event" }, { "id": "58114b8d-7aab-491d-97ce-7b32c0c1d198", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "9b382aaf-50b5-49a2-8b72-8e1ebfe687cb", "type": "raw_event" }, { "id": "976bc217-7b24-4a2e-8c4f-4f4e3597348d", "type": "raw_event" }, { "id": "421ab729-8741-4c9b-a493-b8b93ca1ff13", "type": "raw_event" }, { "id": "0eada15a-7830-4e22-8a30-3c994d7e6130", "type": "raw_event" } ] } } }, { "id": "b80acdc3-e2e7-4d09-8c7a-48ce12b4dd38", "type": "port", "attributes": { "id": "b80acdc3-e2e7-4d09-8c7a-48ce12b4dd38", "name": "Ningbo", "code": "CNNGB", "state_abbr": null, "city": null, "country_code": "CN", "latitude": "29.889437243", "longitude": "122.033720842", "time_zone": "Asia/Shanghai" } }, { "id": "c17c5324-008e-4549-9e67-302cff53a56d", "type": "vessel", "attributes": { "name": "NYK THEMIS", "imo": "9356696", "mmsi": "636018225", "latitude": -78.30435842851921, "longitude": 25.471353799804547, "nautical_speed_knots": 100, "navigational_heading_degrees": 18, "position_timestamp": "2023-06-05T19:46:18Z" } }, { "id": "58114b8d-7aab-491d-97ce-7b32c0c1d198", "type": "transport_event", "attributes": { "event": "container.transport.vessel_loaded", "created_at": "2022-10-21T20:16:47Z", "voyage_number": "0082E", "timestamp": "2022-09-22T09:38:00Z", "data_source": "shipping_line", "location_locode": "CNNGB", "timezone": "Asia/Shanghai" }, "relationships": { "shipment": { "data": { "id": "2bae2c8b-c682-47a6-81c7-f1ac9d4404ef", "type": "shipment" } }, "container": { "data": { "id": "c7876dc6-ccad-4219-b0a2-1e9e9845f474", "type": "container" } }, "vessel": { "data": { "id": "c17c5324-008e-4549-9e67-302cff53a56d", "type": "vessel" } }, "location": { "data": { "id": "b80acdc3-e2e7-4d09-8c7a-48ce12b4dd38", "type": "port" } }, "terminal": { "data": null } } } ] } ``` ## container.updated ```json theme={null} { "data": { "id": "aee69c9e-66e5-4ead-82ee-668dafc242ee", "type": "webhook_notification", "attributes": { "id": "aee69c9e-66e5-4ead-82ee-668dafc242ee", "event": "container.updated", "delivery_status": "succeeded", "created_at": "2022-10-21T20:19:13Z" }, "relationships": { "reference_object": { "data": { "id": "638dd40b-6d1a-48a5-af2f-c68463059149", "type": "container_updated_event" } }, "webhook": { "data": { "id": "fdd1cf95-7569-4bf9-965b-825a55fa6303", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "c0633538-4e53-4c33-bde5-055a5bdbfa29", "type": "shipment", "attributes": { "created_at": "2022-09-06T08:29:58Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "MAEUJAK015053", "normalized_number": "JAK015053", "shipping_line_scac": "MAEU", "shipping_line_name": "Maersk", "shipping_line_short_name": "Maersk", "customer_name": "Lakin and Sons", "port_of_lading_locode": "IDJKT", "port_of_lading_name": "Jakarta, Java", "port_of_discharge_locode": "USNYC", "port_of_discharge_name": "New York / New Jersey", "pod_vessel_name": "MAERSK SYDNEY", "pod_vessel_imo": "9289958", "pod_voyage_number": "235W", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-09-04T16:54:00Z", "pol_timezone": "Asia/Jakarta", "pod_eta_at": "2022-10-10T22:00:00Z", "pod_original_eta_at": "2022-10-14T07:00:00Z", "pod_ata_at": "2022-10-10T22:00:00Z", "pod_timezone": "America/New_York", "line_tracking_last_attempted_at": "2022-10-21T18:11:45Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "82bf3631-280e-4d73-81d8-fc16753d08a7", "type": "port" } }, "port_of_discharge": { "data": { "id": "9e9e8a64-bc96-417f-87d2-189ebccd0123", "type": "port" } }, "pod_terminal": { "data": { "id": "fb4666e2-f159-429e-9d6c-4a09ced32262", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "5f3d40ad-2e2f-4778-8973-8a3a70bef56d", "type": "container" } ] } }, "links": { "self": "/v2/shipments/7297af4f-e047-4a8e-9eda-d1013ce2ab16" } }, { "id": "9e9e8a64-bc96-417f-87d2-189ebccd0123", "type": "port", "attributes": { "id": "9e9e8a64-bc96-417f-87d2-189ebccd0123", "name": "New York / New Jersey", "code": "USNYC", "state_abbr": "NY", "city": "New York", "country_code": "US", "latitude": "40.684996498", "longitude": "-74.151115685", "time_zone": "America/New_York" } }, { "id": "fb4666e2-f159-429e-9d6c-4a09ced32262", "type": "terminal", "attributes": { "id": "fb4666e2-f159-429e-9d6c-4a09ced32262", "nickname": "APM Terminals", "name": "Port Elizabeth", "firms_code": "E425", "smdg_code": null, "bic_facility_code": null, "provided_data": { "pickup_lfd": false, "pickup_lfd_notes": "", "available_for_pickup": false, "fees_at_pod_terminal": false, "holds_at_pod_terminal": false, "pickup_appointment_at": false, "location_at_pod_terminal": false, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": false, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "701 New Dock Street Berths 212-225", "city": "Terminal Island", "state": "California", "state_abbr": "CA", "zip": "90731", "country": "United States" }, "relationships": { "port": { "data": { "id": "9e9e8a64-bc96-417f-87d2-189ebccd0123", "type": "port" } } } }, { "id": "5f3d40ad-2e2f-4778-8973-8a3a70bef56d", "type": "container", "attributes": { "number": "MSKU4807969", "seal_number": null, "created_at": "2022-09-06T08:29:58Z", "ref_numbers": [ ], "pod_arrived_at": "2022-10-10T22:00:00Z", "pod_discharged_at": "2022-10-11T21:32:00Z", "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": true, "equipment_type": "dry", "equipment_length": 45, "equipment_height": "high_cube", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": "2022-10-21T20:19:12Z", "fees_at_pod_terminal": [ ], "pickup_lfd": "2022-10-24T04:00:00Z", "pickup_appointment_at": "2022-10-18T16:00:00Z", "pod_full_out_chassis_number": null, "location_at_pod_terminal": "Yard Grounded (G90402B1)", "pod_last_tracking_request_at": "2022-10-21T20:19:12Z", "shipment_last_tracking_request_at": null, "availability_known": true, "pod_timezone": "America/New_York", "final_destination_timezone": null, "empty_terminated_timezone": "America/New_York" }, "relationships": { "shipment": { "data": { "id": "c0633538-4e53-4c33-bde5-055a5bdbfa29", "type": "shipment" } }, "pod_terminal": { "data": { "id": "fb4666e2-f159-429e-9d6c-4a09ced32262", "type": "terminal" } }, "transport_events": { "data": [ { "id": "e9b1b49a-b84e-469e-ac72-b0026cd0a17a", "type": "transport_event" }, { "id": "dbf8a2b9-d19e-42c1-8bdf-216f075028c8", "type": "transport_event" }, { "id": "4a10db53-cfd1-4a1e-98e3-6dcea72b34b5", "type": "transport_event" }, { "id": "f32b184d-aea7-4a61-98c3-a2e5e7b78775", "type": "transport_event" }, { "id": "87245720-cc9f-4e17-b2df-c76a969b6294", "type": "transport_event" }, { "id": "74d08ccb-0e8c-4715-9d48-d083441764c3", "type": "transport_event" }, { "id": "f700c2f0-edbe-406f-943c-8575e4656af8", "type": "transport_event" }, { "id": "8242486b-0410-40e5-9566-c57cda4a2948", "type": "transport_event" }, { "id": "b6e33165-7848-48b0-a621-2012e6392d6e", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "e6ecd493-4e6b-4d92-809a-ffd73d401d67", "type": "raw_event" }, { "id": "abff03e4-d246-4d2a-b02b-5a5f81d493b5", "type": "raw_event" }, { "id": "603d631b-6a81-4389-94f5-7fe21e71a43e", "type": "raw_event" }, { "id": "3fcc6702-859c-4088-81ea-407f37d83481", "type": "raw_event" }, { "id": "108f5bab-7a33-4fef-bbfc-fc1b12f8742d", "type": "raw_event" }, { "id": "e588e237-7dd1-4982-8fc8-6ce82447cd92", "type": "raw_event" }, { "id": "c796106f-39ce-402e-8296-5a02cafe6da7", "type": "raw_event" }, { "id": "2fb9cdf8-8f9b-4ff2-9a79-e79031f745c6", "type": "raw_event" }, { "id": "aa56172c-c0c4-4fe8-a718-ff95826469ad", "type": "raw_event" } ] } } }, { "id": "638dd40b-6d1a-48a5-af2f-c68463059149", "type": "container_updated_event", "attributes": { "changeset": { "available_for_pickup": [ false, true ], "holds_at_pod_terminal": [ [ { "name": "other", "status": "hold", "description": "DOWN - Broken Machine Over Pile" }, { "name": "other", "status": "hold", "description": "MACHINE - " } ], [ ] ] }, "timestamp": "2022-10-21T20:19:12Z", "data_source": "terminal", "timezone": "America/New_York" }, "relationships": { "container": { "data": { "id": "5f3d40ad-2e2f-4778-8973-8a3a70bef56d", "type": "container" } }, "terminal": { "data": { "id": "fb4666e2-f159-429e-9d6c-4a09ced32262", "type": "terminal" } }, "shipment": { "data": { "id": "c0633538-4e53-4c33-bde5-055a5bdbfa29", "type": "shipment" } } } } ] } ``` ## shipment.estimated.arrival ```json theme={null} { "data": { "id": "0a6b1c26-25c1-4309-b190-ff7cb50f75e3", "type": "webhook_notification", "attributes": { "id": "0a6b1c26-25c1-4309-b190-ff7cb50f75e3", "event": "shipment.estimated.arrival", "delivery_status": "succeeded", "created_at": "2022-10-21T20:19:13Z" }, "relationships": { "reference_object": { "data": { "id": "0db4d1a2-ec3e-4123-9d80-1431c81733e6", "type": "estimated_event" } }, "webhook": { "data": { "id": "5e58fc0c-0686-4156-96cf-410f673d54cb", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "fd0b571a-d6bc-4059-93ed-fc5b00a83b15", "type": "shipment", "attributes": { "created_at": "2022-09-20T02:55:25Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "OOLU2136060630", "normalized_number": "2136060630", "shipping_line_scac": "OOLU", "shipping_line_name": "Orient Overseas Container Line", "shipping_line_short_name": "OOCL", "customer_name": "Casper, Abshire and Dibbert", "port_of_lading_locode": "MYPEN", "port_of_lading_name": "Penang", "port_of_discharge_locode": "USLAX", "port_of_discharge_name": "Los Angeles", "pod_vessel_name": "CMA CGM NORMA", "pod_vessel_imo": "9299812", "pod_voyage_number": "0TUPFE1MA", "destination_locode": "USEWI", "destination_name": "Elwood", "destination_timezone": "America/Chicago", "destination_ata_at": null, "destination_eta_at": "2022-11-07T17:00:00Z", "pol_etd_at": "2022-09-24T18:30:00Z", "pol_atd_at": "2022-09-24T23:35:00Z", "pol_timezone": "Asia/Kuala_Lumpur", "pod_eta_at": "2022-11-01T14:00:00Z", "pod_original_eta_at": "2022-11-03T01:00:00Z", "pod_ata_at": null, "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:18:58Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "7d0a06e4-f894-46ee-96f5-407d7cc7db1b", "type": "port" } }, "port_of_discharge": { "data": { "id": "56adff5b-0ec1-4b81-985f-3380bca38b0b", "type": "port" } }, "pod_terminal": { "data": { "id": "e37931e1-d68e-497f-bd7c-6bb4ebf00520", "type": "terminal" } }, "destination": { "data": { "id": "fc2e0c64-0491-400c-afe8-a5e8dca77c7c", "type": "metro_area" } }, "destination_terminal": { "data": { "id": "ed03e950-a528-4b3d-bf6b-15141e397dc5", "type": "rail_terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "300f6e6f-04ba-4f49-b9bd-7302fc382c4d", "type": "container" } ] } }, "links": { "self": "/v2/shipments/4f363cf9-8d55-4709-bf64-77f4bd7ed824" } }, { "id": "56adff5b-0ec1-4b81-985f-3380bca38b0b", "type": "port", "attributes": { "id": "56adff5b-0ec1-4b81-985f-3380bca38b0b", "name": "Los Angeles", "code": "USLAX", "state_abbr": "CA", "city": "Los Angeles", "country_code": "US", "latitude": "33.728193631", "longitude": "-118.255820307", "time_zone": "America/Los_Angeles" } }, { "id": "0db4d1a2-ec3e-4123-9d80-1431c81733e6", "type": "estimated_event", "attributes": { "created_at": "2022-10-21T20:19:13Z", "estimated_timestamp": "2022-11-01T14:00:00Z", "voyage_number": "0TUPFE1MA", "event": "shipment.estimated.arrival", "location_locode": "USLAX", "data_source": "shipping_line", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "fd0b571a-d6bc-4059-93ed-fc5b00a83b15", "type": "shipment" } }, "port": { "data": { "id": "56adff5b-0ec1-4b81-985f-3380bca38b0b", "type": "port" } }, "vessel": { "data": { "id": "3f97ddb7-2e53-4ed1-ae22-04b82b340136", "type": "vessel" } } } } ] } ``` ## shipment.transport.vessel\_arrived ```json theme={null} { "data": { "id": "1ababdd7-3d93-436d-8fc7-e8029bb4b466", "type": "webhook_notification", "attributes": { "id": "1ababdd7-3d93-436d-8fc7-e8029bb4b466", "event": "shipment.transport.vessel_arrived", "delivery_status": "succeeded", "created_at": "2020-05-11T15:09:58Z" }, "relationships": { "reference_object": { "data": { "id": "e400b938-19d9-4d78-888f-351af48a915e", "type": "transport_event" } }, "webhook": { "data": { "id": "a3ea832c-179c-4fd9-891d-5765a77af9d4", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } } } ``` ## tracking\_request.awaiting\_manifest ```json theme={null} { "data": { "id": "b7235d00-2617-434e-9e28-a5cf83a0a0d3", "type": "webhook_notification", "attributes": { "id": "b7235d00-2617-434e-9e28-a5cf83a0a0d3", "event": "tracking_request.awaiting_manifest", "delivery_status": "succeeded", "created_at": "2022-10-21T20:15:54Z" }, "relationships": { "reference_object": { "data": { "id": "ff77f76c-5e73-47c4-ab1e-d499cb1fa10f", "type": "tracking_request" } }, "webhook": { "data": { "id": "bb30c47d-db43-4fa0-9287-7bfade47e4ec", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "ff77f76c-5e73-47c4-ab1e-d499cb1fa10f", "type": "tracking_request", "attributes": { "request_number": "IZ12208APRV6", "request_type": "bill_of_lading", "scac": "HLCU", "ref_numbers": [ ], "shipment_tags": [ ], "created_at": "2022-10-21T20:15:49Z", "updated_at": "2022-10-21T21:15:49Z", "status": "awaiting_manifest", "failed_reason": null, "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": null }, "customer": { "data": null }, "user": { "data": null } }, "links": { "self": "/v2/tracking_requests/ca388055-8e3a-4b85-8401-e4aa1abf7228" } } ] } ``` ## tracking\_request.failed ```json theme={null} { "data": { "id": "dfa9f92b-dbc5-403e-b03f-d5683abbd074", "type": "webhook_notification", "attributes": { "id": "dfa9f92b-dbc5-403e-b03f-d5683abbd074", "event": "tracking_request.failed", "delivery_status": "pending", "created_at": "2022-10-21T20:19:14Z" }, "relationships": { "reference_object": { "data": { "id": "5fe62a78-86af-4408-a79c-2d03c907a68b", "type": "tracking_request" } }, "webhook": { "data": { "id": "5c7cbf41-37f4-4e76-b06b-4b17860fab02", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "5fe62a78-86af-4408-a79c-2d03c907a68b", "type": "tracking_request", "attributes": { "request_number": "MAEU11875506", "request_type": "bill_of_lading", "scac": "MAEU", "ref_numbers": [ ], "shipment_tags": [ ], "created_at": "2022-10-21T20:19:13Z", "updated_at": "2022-10-21T21:19:13Z", "status": "failed", "failed_reason": "not_found", "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": null }, "customer": { "data": null }, "user": { "data": null } }, "links": { "self": "/v2/tracking_requests/93d0d469-cbcf-4b6c-ae59-526c176942c7" } } ] } ``` ## tracking\_request.succeeded ```json theme={null} { "data": { "id": "0b27a595-e531-4f93-8d5a-22e1675d863a", "type": "webhook_notification", "attributes": { "id": "0b27a595-e531-4f93-8d5a-22e1675d863a", "event": "tracking_request.succeeded", "delivery_status": "succeeded", "created_at": "2022-10-21T20:18:36Z" }, "relationships": { "reference_object": { "data": { "id": "bf1d2f9d-f88a-4aed-901b-a86cddb0a665", "type": "tracking_request" } }, "webhook": { "data": { "id": "b1617bb8-d713-4450-8dd7-81be1317631c", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "2444986c-5ebe-4bc5-ad55-d24293424943", "type": "container", "attributes": { "number": "MRKU3700927", "seal_number": null, "created_at": "2022-10-21T20:18:36Z", "ref_numbers": [ ], "pod_arrived_at": null, "pod_discharged_at": null, "final_destination_full_out_at": null, "holds_at_pod_terminal": [ ], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": null, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [ ], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": null, "availability_known": false, "pod_timezone": null, "final_destination_timezone": null, "empty_terminated_timezone": null }, "relationships": { "shipment": { "data": { "id": "6af82332-9bff-4b4a-a1e1-a382e0f82ca5", "type": "shipment" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ ] }, "raw_events": { "data": [ ] } } }, { "id": "6af82332-9bff-4b4a-a1e1-a382e0f82ca5", "type": "shipment", "attributes": { "created_at": "2022-10-21T20:18:36Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "MAEU221876618", "normalized_number": "221876618", "shipping_line_scac": "MAEU", "shipping_line_name": "Maersk", "shipping_line_short_name": "Maersk", "customer_name": "Schuster-Barrows", "port_of_lading_locode": "CNNGB", "port_of_lading_name": "Ningbo", "port_of_discharge_locode": null, "port_of_discharge_name": null, "pod_vessel_name": null, "pod_vessel_imo": null, "pod_voyage_number": null, "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": null, "pol_timezone": "Asia/Shanghai", "pod_eta_at": "2022-11-25T08:00:00Z", "pod_original_eta_at": "2022-11-25T08:00:00Z", "pod_ata_at": null, "pod_timezone": null, "line_tracking_last_attempted_at": null, "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "relationships": { "port_of_lading": { "data": { "id": "d741a6bc-13dd-4b62-a5c2-f65050c9403d", "type": "port" } }, "port_of_discharge": { "data": null }, "pod_terminal": { "data": null }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "2444986c-5ebe-4bc5-ad55-d24293424943", "type": "container" } ] } }, "links": { "self": "/v2/shipments/e5a39855-f438-467a-9c18-ae91cd46cfaf" } }, { "id": "bf1d2f9d-f88a-4aed-901b-a86cddb0a665", "type": "tracking_request", "attributes": { "request_number": "MAEU221876618", "request_type": "bill_of_lading", "scac": "MAEU", "ref_numbers": [ ], "shipment_tags": [ ], "created_at": "2022-10-17T14:17:30Z", "updated_at": "2022-10-17T15:17:30Z", "status": "created", "failed_reason": null, "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": { "id": "6af82332-9bff-4b4a-a1e1-a382e0f82ca5", "type": "shipment" } }, "customer": { "data": null }, "user": { "data": null } }, "links": { "self": "/v2/tracking_requests/61e7fc09-e1a0-4bfa-b559-49d7576c790e" } } ] } ``` ## tracking\_request.tracking\_stopped ```json theme={null} { "data": { "id": "00cbaa34-c487-419c-b5c4-415da5478971", "type": "webhook_notification", "attributes": { "id": "00cbaa34-c487-419c-b5c4-415da5478971", "event": "tracking_request.tracking_stopped", "delivery_status": "pending", "created_at": "2022-11-22T16:39:42Z" }, "relationships": { "reference_object": { "data": { "id": "94f2d7a0-4a10-42e0-81d8-83cbabc4ef6c", "type": "tracking_request" } }, "webhook": { "data": { "id": "85336ef9-8901-45fc-95c1-d26bc8f2bf68", "type": "webhook" } }, "webhook_notification_logs": { "data": [ ] } } }, "included": [ { "id": "36917159-1982-4c0e-bb7e-7a5e972d9c1b", "type": "shipment", "attributes": { "created_at": "2022-09-15T17:52:08Z", "ref_numbers": [ ], "tags": [ ], "bill_of_lading_number": "CMDUAMC1863476", "normalized_number": "AMC1863476", "shipping_line_scac": "CMDU", "shipping_line_name": "CMA CGM", "shipping_line_short_name": "CMA CGM", "customer_name": "Miller-Gleason", "port_of_lading_locode": "INNSA", "port_of_lading_name": "Nhava Sheva", "port_of_discharge_locode": "USLAX", "port_of_discharge_name": "Los Angeles", "pod_vessel_name": "EVER LOVELY", "pod_vessel_imo": "9629110", "pod_voyage_number": "0TBD0W1MA", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2022-07-20T17:59:00Z", "pol_timezone": "Asia/Calcutta", "pod_eta_at": "2022-09-14T14:00:00Z", "pod_original_eta_at": "2022-09-14T14:00:00Z", "pod_ata_at": "2022-09-16T08:11:18Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2022-10-21T20:01:32Z", "line_tracking_last_succeeded_at": null, "line_tracking_stopped_at": "2022-11-22T16:39:42Z", "line_tracking_stopped_reason": "account_closed" }, "relationships": { "port_of_lading": { "data": { "id": "256aec7d-4915-48d4-b8e5-911e097b05e7", "type": "port" } }, "port_of_discharge": { "data": { "id": "786ff548-7e55-4d18-b4a6-b6ee31b4cc62", "type": "port" } }, "pod_terminal": { "data": { "id": "46648f15-fcf3-49fc-b86f-e8550b95c40c", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": null }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "bb77de85-2e89-4596-8a74-6100f3180296", "type": "container" } ] } }, "links": { "self": "/v2/shipments/7fd3135d-9da7-4dad-87e3-63242343e182" } }, { "id": "94f2d7a0-4a10-42e0-81d8-83cbabc4ef6c", "type": "tracking_request", "attributes": { "request_number": "CMDUAMC1863476", "request_type": "bill_of_lading", "scac": "CMDU", "ref_numbers": [ ], "shipment_tags": [ ], "created_at": "2022-09-15T17:52:07Z", "updated_at": "2022-09-15T18:52:07Z", "status": "tracking_stopped", "failed_reason": null, "is_retrying": false, "retry_count": null }, "relationships": { "tracked_object": { "data": { "id": "36917159-1982-4c0e-bb7e-7a5e972d9c1b", "type": "shipment" } }, "customer": { "data": null }, "user": { "data": { "id": "3d28c8cb-9cbb-471d-b946-80e7345c9572", "type": "user" } } }, "links": { "self": "/v2/tracking_requests/c871c4b8-0436-410c-8b39-fd426e06869e" } } ] } ``` ## container.transport.arrived\_at\_inland\_destination ```json theme={null} { "data": { "id": "51cc2480-760e-4ce6-af36-a69669292cad", "type": "webhook_notification", "attributes": { "id": "51cc2480-760e-4ce6-af36-a69669292cad", "event": "container.transport.arrived_at_inland_destination", "delivery_status": "pending", "created_at": "2024-06-26T21:21:53Z" }, "relationships": { "reference_object": { "data": { "id": "1a61d6af-64ee-4f45-846d-59e0b8b257d0", "type": "transport_event" } }, "webhook": { "data": { "id": "9fc3b3b6-5551-4b76-b0c7-d9bb1e86ed26", "type": "webhook" } }, "webhook_notification_logs": { "data": [] } } }, "links": { "self": "https://api.terminal49.com/v2/webhook_notifications/examples?event=container.transport.arrived_at_inland_destination" }, "included": [ { "id": "e7a78724-6ddd-48a2-85c9-e88def7a8406", "type": "shipment", "attributes": { "created_at": "2024-06-26T21:21:52Z", "ref_numbers": [ "REF-4DB6E7", "REF-045A0E" ], "tags": [], "bill_of_lading_number": "TE49BB993AAD", "normalized_number": "TE49BB993AAD", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "customer_name": "Rempel-Becker", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2024-06-13T21:21:52Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2024-07-03T21:21:52Z", "pod_original_eta_at": "2024-07-03T21:21:52Z", "pod_ata_at": "2024-07-03T22:21:52Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2024-06-26T21:21:52Z", "line_tracking_last_succeeded_at": "2024-06-26T21:21:52Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "links": { "self": "/v2/shipments/e7a78724-6ddd-48a2-85c9-e88def7a8406" }, "relationships": { "port_of_lading": { "data": { "id": "dd85723f-17a6-4b7a-bd98-c6f0d94fe4e6", "type": "port" } }, "port_of_discharge": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "pod_terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "a88159cc-9c76-492f-a145-003352ef8e92", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "30c56cea-b155-4618-a365-a1d77d5bdac5", "type": "container" } ] } } }, { "id": "30c56cea-b155-4618-a365-a1d77d5bdac5", "type": "container", "attributes": { "number": "OERU4412200", "seal_number": "f6ab033e15ec49fd", "created_at": "2024-06-26T21:21:53Z", "ref_numbers": [ "REF-ED3A41" ], "pod_arrived_at": "2024-06-26T21:21:52Z", "pod_discharged_at": "2024-06-26T21:21:52Z", "final_destination_full_out_at": "2024-06-26T21:21:52Z", "holds_at_pod_terminal": [], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 53443, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": "2024-06-26T21:21:52Z", "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "e7a78724-6ddd-48a2-85c9-e88def7a8406", "type": "shipment" } }, "pickup_facility": { "data": { "id": "a88159cc-9c76-492f-a145-003352ef8e92", "type": "terminal" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "1a61d6af-64ee-4f45-846d-59e0b8b257d0", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "807f7867-9f4b-467b-b5be-c297eba40533", "type": "raw_event" }, { "id": "3a03c7a3-8aec-4f33-8603-3050b974cbef", "type": "raw_event" }, { "id": "45df4091-4b77-4526-b7ec-b3619c14f1fd", "type": "raw_event" }, { "id": "6ff26f49-ca58-4a3f-92e1-db0f295b6a5c", "type": "raw_event" }, { "id": "141ad992-befb-4951-8421-bf84dfed1fb8", "type": "raw_event" }, { "id": "1621ff9e-e45d-4151-a9ee-6f242fa61d0d", "type": "raw_event" }, { "id": "06f3f0c3-8ab8-4cf4-b442-0de4e7147dbf", "type": "raw_event" }, { "id": "f6681a35-b760-45f6-a69f-66fa81be5ea8", "type": "raw_event" }, { "id": "423481e2-4e8f-45c0-8707-92742dc7ba60", "type": "raw_event" }, { "id": "09bef6df-0dcd-4a84-99da-038a5f64261b", "type": "raw_event" }, { "id": "c3b334ed-9ade-45f5-bfd1-66d26a28351a", "type": "raw_event" } ] } } }, { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port", "attributes": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "latitude": "37.8044", "longitude": "-122.2712", "time_zone": "America/Los_Angeles" } }, { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal", "attributes": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985", "smdg_code": "B58", "bic_facility_code": "USOAKTYJE", "provided_data": { "pickup_lfd": true, "pod_full_out_at": true, "pickup_lfd_notes": "", "available_for_pickup": true, "fees_at_pod_terminal": true, "holds_at_pod_terminal": true, "pickup_appointment_at": false, "location_at_pod_terminal": true, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": true, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "880 Koepp Manors", "city": "South Dustin", "state": "West Virginia", "state_abbr": "AR", "zip": "71794", "country": "Lithuania", "facility_type": "ocean_terminal" }, "relationships": { "port": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } } } }, { "id": "1a61d6af-64ee-4f45-846d-59e0b8b257d0", "type": "transport_event", "attributes": { "event": "container.transport.vessel_arrived", "created_at": "2024-06-26T21:21:52Z", "voyage_number": null, "timestamp": "2024-06-26T21:21:52Z", "data_source": "shipping_line", "location_locode": "USOAK", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "e7a78724-6ddd-48a2-85c9-e88def7a8406", "type": "shipment" } }, "container": { "data": { "id": "30c56cea-b155-4618-a365-a1d77d5bdac5", "type": "container" } }, "vessel": { "data": { "id": "daf64780-ecdd-4d46-ae4a-eb70968069ed", "type": "vessel" } }, "location": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } } } } ] } ``` ## container.transport.estimated.arrived\_at\_inland\_destination ```json theme={null} { "data": { "id": "2ff96102-8016-41d8-a313-1fcbf4cba2cc", "type": "webhook_notification", "attributes": { "id": "2ff96102-8016-41d8-a313-1fcbf4cba2cc", "event": "container.transport.estimated.arrived_at_inland_destination", "delivery_status": "pending", "created_at": "2024-06-26T21:22:22Z" }, "relationships": { "reference_object": { "data": { "id": "ce3376bf-ed14-43ea-b0cd-9ebd5105be7b", "type": "transport_event" } }, "webhook": { "data": { "id": "188e6629-d9e0-446e-8dd8-078090eba7b3", "type": "webhook" } }, "webhook_notification_logs": { "data": [] } } }, "links": { "self": "https://api.terminal49.com/v2/webhook_notifications/examples?event=container.transport.estimated.arrived_at_inland_destination" }, "included": [ { "id": "a8d9896f-a483-4548-9bae-3107e6adca3b", "type": "shipment", "attributes": { "created_at": "2024-06-26T21:22:21Z", "ref_numbers": [ "REF-7B250E" ], "tags": [], "bill_of_lading_number": "TE492FCF3119", "normalized_number": "TE492FCF3119", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "customer_name": "Gerlach, Hettinger and Mitchell", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2024-06-13T21:22:21Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2024-07-03T21:22:21Z", "pod_original_eta_at": "2024-07-03T21:22:21Z", "pod_ata_at": "2024-07-03T22:22:21Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2024-06-26T21:22:21Z", "line_tracking_last_succeeded_at": "2024-06-26T21:22:21Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "links": { "self": "/v2/shipments/a8d9896f-a483-4548-9bae-3107e6adca3b" }, "relationships": { "port_of_lading": { "data": { "id": "dd85723f-17a6-4b7a-bd98-c6f0d94fe4e6", "type": "port" } }, "port_of_discharge": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "pod_terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "99a517a6-b7a1-49aa-9012-2d03d7aff720", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "eb48ec6e-3057-44b6-8aee-db1fbd8705e3", "type": "container" } ] } } }, { "id": "eb48ec6e-3057-44b6-8aee-db1fbd8705e3", "type": "container", "attributes": { "number": "GLDU9577709", "seal_number": "fcbe2b0c3fa3e367", "created_at": "2024-06-26T21:22:22Z", "ref_numbers": [ "REF-2A857F", "REF-ADB003" ], "pod_arrived_at": "2024-06-26T21:22:21Z", "pod_discharged_at": "2024-06-26T21:22:21Z", "final_destination_full_out_at": "2024-06-26T21:22:21Z", "holds_at_pod_terminal": [], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 54472, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": "2024-06-26T21:22:21Z", "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "a8d9896f-a483-4548-9bae-3107e6adca3b", "type": "shipment" } }, "pickup_facility": { "data": { "id": "99a517a6-b7a1-49aa-9012-2d03d7aff720", "type": "terminal" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "ce3376bf-ed14-43ea-b0cd-9ebd5105be7b", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "9da5b426-9e08-4d82-913e-fc3e0b1b5b69", "type": "raw_event" }, { "id": "5f8809ef-4d80-4ffa-8e92-faba48a3909e", "type": "raw_event" }, { "id": "13651871-42bb-4c97-b3e2-9cc3b5737da7", "type": "raw_event" }, { "id": "dda7f006-c741-43c4-9ab3-019f391dae13", "type": "raw_event" }, { "id": "c7ec67f1-bfb0-47ca-9515-7f4f1449dffc", "type": "raw_event" }, { "id": "44325279-6fbe-46c8-9138-52732d5128b6", "type": "raw_event" }, { "id": "51539ed3-10c7-4f22-955f-07c27321fbb7", "type": "raw_event" }, { "id": "ea9f5732-404b-4c7d-a98c-ad960bd0632c", "type": "raw_event" }, { "id": "3361e110-9cc3-4023-a162-3301adb342f1", "type": "raw_event" }, { "id": "d6b4cb90-f93d-4e0e-a1c9-1f6593e60e2c", "type": "raw_event" }, { "id": "5404e2a6-945a-4c2f-923c-15efab1aadf6", "type": "raw_event" } ] } } }, { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port", "attributes": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "latitude": "37.8044", "longitude": "-122.2712", "time_zone": "America/Los_Angeles" } }, { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal", "attributes": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985", "smdg_code": "B58", "bic_facility_code": "USOAKTYJE", "provided_data": { "pickup_lfd": true, "pod_full_out_at": true, "pickup_lfd_notes": "", "available_for_pickup": true, "fees_at_pod_terminal": true, "holds_at_pod_terminal": true, "pickup_appointment_at": false, "location_at_pod_terminal": true, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": true, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "806 Lillia Forks", "city": "South Edison", "state": "Colorado", "state_abbr": "KY", "zip": "47421", "country": "Mauritius", "facility_type": "ocean_terminal" }, "relationships": { "port": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } } } }, { "id": "ce3376bf-ed14-43ea-b0cd-9ebd5105be7b", "type": "transport_event", "attributes": { "event": "container.transport.vessel_arrived", "created_at": "2024-06-26T21:22:21Z", "voyage_number": null, "timestamp": "2024-06-26T21:22:21Z", "data_source": "shipping_line", "location_locode": "USOAK", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "a8d9896f-a483-4548-9bae-3107e6adca3b", "type": "shipment" } }, "container": { "data": { "id": "eb48ec6e-3057-44b6-8aee-db1fbd8705e3", "type": "container" } }, "vessel": { "data": { "id": "daf64780-ecdd-4d46-ae4a-eb70968069ed", "type": "vessel" } }, "location": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } } } } ] } ``` ## container.pickup\_lfd.changed ```json theme={null} { "data": { "id": "4f95eaca-ebd1-414d-b50f-84e113a01b37", "type": "webhook_notification", "attributes": { "id": "4f95eaca-ebd1-414d-b50f-84e113a01b37", "event": "container.pickup_lfd.changed", "delivery_status": "pending", "created_at": "2024-06-26T21:22:47Z" }, "relationships": { "reference_object": { "data": { "id": "82099f21-0a1d-40bd-b56c-30461f7db1cc", "type": "transport_event" } }, "webhook": { "data": { "id": "046cf6b8-ae02-47e2-90d4-d6379319bb71", "type": "webhook" } }, "webhook_notification_logs": { "data": [] } } }, "links": { "self": "https://api.terminal49.com/v2/webhook_notifications/examples?event=container.pickup_lfd.changed" }, "included": [ { "id": "29a59f1d-cd71-4c0c-9be8-bc453f945d27", "type": "shipment", "attributes": { "created_at": "2024-06-26T21:22:46Z", "ref_numbers": [ "REF-D79122" ], "tags": [], "bill_of_lading_number": "TE491A648538", "normalized_number": "TE491A648538", "shipping_line_scac": "MSCU", "shipping_line_name": "Mediterranean Shipping Company", "shipping_line_short_name": "MSC", "customer_name": "Muller-Hauck", "port_of_lading_locode": "MXZLO", "port_of_lading_name": "Manzanillo", "port_of_discharge_locode": "USOAK", "port_of_discharge_name": "Port of Oakland", "pod_vessel_name": "MSC CHANNE", "pod_vessel_imo": "9710438", "pod_voyage_number": "098N", "destination_locode": null, "destination_name": null, "destination_timezone": null, "destination_ata_at": null, "destination_eta_at": null, "pol_etd_at": null, "pol_atd_at": "2024-06-13T21:22:46Z", "pol_timezone": "America/Mexico_City", "pod_eta_at": "2024-07-03T21:22:46Z", "pod_original_eta_at": "2024-07-03T21:22:46Z", "pod_ata_at": "2024-07-03T22:22:46Z", "pod_timezone": "America/Los_Angeles", "line_tracking_last_attempted_at": "2024-06-26T21:22:46Z", "line_tracking_last_succeeded_at": "2024-06-26T21:22:46Z", "line_tracking_stopped_at": null, "line_tracking_stopped_reason": null }, "links": { "self": "/v2/shipments/29a59f1d-cd71-4c0c-9be8-bc453f945d27" }, "relationships": { "port_of_lading": { "data": { "id": "dd85723f-17a6-4b7a-bd98-c6f0d94fe4e6", "type": "port" } }, "port_of_discharge": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "pod_terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } }, "destination": { "data": null }, "destination_terminal": { "data": { "id": "a40d96ef-3f53-4289-b371-8d26a2aaeff8", "type": "terminal" } }, "line_tracking_stopped_by_user": { "data": null }, "containers": { "data": [ { "id": "3d2ce91a-6ac8-4053-a6fb-7dac1c47bf71", "type": "container" } ] } } }, { "id": "3d2ce91a-6ac8-4053-a6fb-7dac1c47bf71", "type": "container", "attributes": { "number": "OERU6438708", "seal_number": "16082b290c25f0c5", "created_at": "2024-06-26T21:22:47Z", "ref_numbers": [ "REF-2E50D1" ], "pod_arrived_at": "2024-06-26T21:22:46Z", "pod_discharged_at": "2024-06-26T21:22:46Z", "final_destination_full_out_at": "2024-06-26T21:22:46Z", "holds_at_pod_terminal": [], "available_for_pickup": false, "equipment_type": "dry", "equipment_length": 40, "equipment_height": "standard", "weight_in_lbs": 60753, "pod_full_out_at": null, "empty_terminated_at": null, "terminal_checked_at": null, "fees_at_pod_terminal": [], "pickup_lfd": null, "pickup_appointment_at": null, "pod_full_out_chassis_number": null, "location_at_pod_terminal": null, "pod_last_tracking_request_at": null, "shipment_last_tracking_request_at": "2024-06-26T21:22:46Z", "availability_known": true, "pod_timezone": "America/Los_Angeles", "final_destination_timezone": null, "empty_terminated_timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "29a59f1d-cd71-4c0c-9be8-bc453f945d27", "type": "shipment" } }, "pickup_facility": { "data": { "id": "a40d96ef-3f53-4289-b371-8d26a2aaeff8", "type": "terminal" } }, "pod_terminal": { "data": null }, "transport_events": { "data": [ { "id": "82099f21-0a1d-40bd-b56c-30461f7db1cc", "type": "transport_event" } ] }, "raw_events": { "data": [ { "id": "4327e350-4a73-4960-9842-e2a228477e8a", "type": "raw_event" }, { "id": "5e51cdbb-3dd9-42d5-9d1e-30aca590b874", "type": "raw_event" }, { "id": "f2b4c0e4-2f53-4653-82d4-31c5d68a9886", "type": "raw_event" }, { "id": "350e6c50-8594-48c7-845d-c657f841f46c", "type": "raw_event" }, { "id": "57794561-bae5-4f9b-9d14-24b35da518eb", "type": "raw_event" }, { "id": "8c50848d-15b4-4155-a504-e8df4c9ae7e4", "type": "raw_event" }, { "id": "c3abbd18-198c-441e-8c46-9033ee5bdfbc", "type": "raw_event" }, { "id": "9160cf78-5414-4eb1-853a-519a03e83879", "type": "raw_event" }, { "id": "69f5b333-53a0-40ee-a759-375f6cae04df", "type": "raw_event" }, { "id": "1f7c900c-2940-4c6b-a132-397a9ca075aa", "type": "raw_event" }, { "id": "2c9e5f2f-df5d-4992-b33e-088f37e123f8", "type": "raw_event" } ] } } }, { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port", "attributes": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "name": "Port of Oakland", "code": "USOAK", "state_abbr": "CA", "city": "Oakland", "country_code": "US", "latitude": "37.8044", "longitude": "-122.2712", "time_zone": "America/Los_Angeles" } }, { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal", "attributes": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "nickname": "SSA", "name": "SSA Terminal", "firms_code": "Z985", "smdg_code": "B58", "bic_facility_code": "USOAKTYJE", "provided_data": { "pickup_lfd": true, "pod_full_out_at": true, "pickup_lfd_notes": "", "available_for_pickup": true, "fees_at_pod_terminal": true, "holds_at_pod_terminal": true, "pickup_appointment_at": false, "location_at_pod_terminal": true, "available_for_pickup_notes": "", "fees_at_pod_terminal_notes": "", "holds_at_pod_terminal_notes": "", "pickup_appointment_at_notes": "", "pod_full_out_chassis_number": true, "location_at_pod_terminal_notes": "", "pod_full_out_chassis_number_notes": "" }, "street": "636 Volkman Valleys", "city": "Lake Jame", "state": "Indiana", "state_abbr": "TN", "zip": "34546-1736", "country": "Saint Lucia", "facility_type": "ocean_terminal" }, "relationships": { "port": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } } } }, { "id": "82099f21-0a1d-40bd-b56c-30461f7db1cc", "type": "transport_event", "attributes": { "event": "container.transport.vessel_arrived", "created_at": "2024-06-26T21:22:46Z", "voyage_number": null, "timestamp": "2024-06-26T21:22:46Z", "data_source": "shipping_line", "location_locode": "USOAK", "timezone": "America/Los_Angeles" }, "relationships": { "shipment": { "data": { "id": "29a59f1d-cd71-4c0c-9be8-bc453f945d27", "type": "shipment" } }, "container": { "data": { "id": "3d2ce91a-6ac8-4053-a6fb-7dac1c47bf71", "type": "container" } }, "vessel": { "data": { "id": "daf64780-ecdd-4d46-ae4a-eb70968069ed", "type": "vessel" } }, "location": { "data": { "id": "42d1ba3a-f4b8-431d-a6fe-49fd748a59e7", "type": "port" } }, "terminal": { "data": { "id": "3e550f0e-ac2a-48fb-b242-5be45ecf2c78", "type": "terminal" } } } } ] } ``` ## container.transport.available ```json theme={null} { "data": { "id": "fb111726-d489-4ef7-bac9-d39f2cbe66ba", "type": "webhook_notification", "attributes": { "id": "fb111726-d489-4ef7-bac9-d39f2cbe66ba", "event": "container.transport.available", "delivery_status": "succeeded", "created_at": "2025-02-26T12:51:52Z" }, "relationships": { "reference_object": { "data": { "id": "7adced6b-0ae4-4554-8c51-f85e58e57eb7", "type": "transport_event" } }, "webhook": { "data": { "id": "91357e6c-43f9-49c2-b052-a2941a003751", "type": "webhook" } }, "webhook_notification_logs": { "data": [] } } }, "links": { "self": "https://api.terminal49.com/v2/webhook_notifications/fb111726-d489-4ef7-bac9-d39f2cbe66ba" } } ``` # Terminal49 Dev Documentation Source: https://terminal49.com/docs/datasync/home We offer two fantastic ways to track your shipments from origin to destination. 1. [Terminal49 DataSync](/datasync/overview). Get tables full of fresh information delivered into your current data system. Easy to set up, and perfect for complementing your current data. 2. [Terminal49 API](/api-docs/getting-started/start-here). Connect directly with the API, pull data for specific shipments and containers, and get updates via webhooks. If you already have a data store that feeds the rest of your system, DataSync is probably what you want. ## What can I use Terminal49 data for? Here are just a few of the data points we return and possible use-cases. | DATA | EXAMPLE USE CASE | | -------------------------------------- | ------------------------------------------------------------------------ | | Destination ETA | Surface ETA changes to your relevant teams as they're reported | | Last Free Day and terminal statusΒΉ | Track containers approaching LFD and prioritize dispatching | | Fees and holds at destination terminal | Clear your cargo to keep you containers moving | | Actual departure and arrival times | Report journey times by route to compare your ocean carriers performance | *1. At container ports in the US* ## How it works All you need to provide are your BOL numbers and SCACs. Terminal 49 will lookup the shipment with the carrier and populate shipment details including containers. Once the shipment is set up, Terminal 49 periodically checks with the carrier and the destination terminal. If any of the details of your shipment or containers change (for example - if the ETA changes) we'll ensure you're always kept up to date. * If you're using DataSync, we'll update the data in your system * If you're using the API, we'll post the shipment to the the webhook you provide πŸ‘ˆπŸ½ Please click API Docs or Data Sync on the left to get started! # Overview Source: https://terminal49.com/docs/datasync/overview DataSync is the easiest way to get fresh, up-to-date container and shipment data into your system. DataSync will create 3 tables in your system, in the schema / dataset / folder / spreadsheet of your choice: [containers](/datasync/table-properties/containers_rail), [shipments](/datasync/table-properties/shipments), and [tracking\_requests](/datasync/table-properties/tracking-requests). In addition to these 3 tables, a technical table named [\_transfer\_status](/datasync/table-properties/transfer-status) is also created, which tells you when each table was last refreshed. We can send the data to almost any database, data warehouse, or object store, as well as to Google Sheets. See the [full list of supported systems](/datasync/supported-destinations). ## How often does the data update? DataSync will keep the data tables updated with a refresh every hour. Each refresh reloads only the rows that have been changed since the previous refresh, so you won't have excess writes to your system. To check when a table was last updated, check the [\_transfer\_status](/datasync/table-properties/transfer-status) table - for each row in that table there is a unique table key, and the time when the latest sync occurred for that table. ## How to use the data You can use the container and shipment tracking data any way you like, but here are a couple ideas: * Send data directly to your visualization/analytics/reports software like PowerBI or Tableau * Send data directly to your TMS or ERP * Join data with one of your own tables * Use a Database View or Pivot Table to narrow down what you're looking at, or rename columns * Use Database Triggers to respond to updates ## The setup process For users that are already tracking shipments with Terminal49, the setup is a 3-step process that takes less than 2 hours on average. Some simpler setups are done in 20 minutes. See below for ways to get data into the system. 1. **Connect data systems**. This could mean doing role-based auth or sharing credentials for a single-purpose user. See our [security FAQ](https://help.terminal49.com/en/articles/7988732-security-considerations-for-terminal49-datasync) if you want to know more about how we keep your data secure. 2. **1-hour configuration call**. We make sure you're getting data the way you want, configuring it to fit in with 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. [Schedule a call with our Customer Success team now](https://meetings.hubspot.com/kyle-blount) to get started. ## How to start tracking shipments There are many ways you can start tracking shipments with Terminal49. They all require that you have the Booking Number or Master Bill of Lading number for the shipments you want to track. * [Send an email with a CSV to track@terminal49.com](https://help.terminal49.com/en/articles/5506959-how-to-add-shipments-via-email) * Upload a CSV through [our dashboard](https://app.terminal49.com/shipments/imports/new) * Input shipments directly through [our dashboard](https://app.terminal49.com/shipments/imports/new) * [Use the Terminal49 API to create TrackingRequests](/api-docs/api-reference/tracking-requests/create-a-tracking-request) ## Getting Started Schedule your call now! For current Terminal49 customers, [schedule a call with our Customer Support team](https://meetings.hubspot.com/kyle-blount) we'll get you set up. If you're not yet a customer, [schedule a demo with our sales team](https://www.terminal49.com/contact) - they'll help you find the solution that's best for you. # Supported Destinations Source: https://terminal49.com/docs/datasync/supported-destinations Terminal49 DataSync directly supports over a dozen different destinations out of the box. Tools like **Excel**, **Power BI**, and **many TMS and ERP systems** can read data from a database or data warehouse. We can feed data into your system and indirectly power those tools. Don’t see your supported database or tool? Please [reach out](https://www.terminal49.com/contact). ## Spreadsheets * Google Sheets ## Databases * MariaDB * Microsoft SQL Server * MySQL * Postgres * SingleStore ## Data Warehouses * Amazon Athena * Amazon Redshift * Clickhouse * Databricks * Firebolt * Google BigQuery * Snowflake ## Object Store * Amazon S3 * Azure Blob Store * Cloudflare R2 * Google Cloud Storage ## Other Systems If you have something like **Excel**, **Power BI/Tableau**, or a **TMS** or **ERP** system, contact your IT team to see what database, data warehouse, or object store is powering them. We can [securely](https://help.terminal49.com/en/articles/7988732-security-considerations-for-terminal49-datasync) feed data into most systems. # Containers (deprecated) Source: https://terminal49.com/docs/datasync/table-properties/containers *This is a deprecated version of the `containers` table, used by DataSync customers before September 2024.* The `containers` table contains 1 row per container (`container_id` is the unique key). Each container is part of 1 shipment (`shipment_id`). This is a large table with denormalized columns to make it easy to use for reporting purposes. | COLUMN NAME | DESCRIPTION | TYPE | | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------- | | `container_id` | Container ID. This is the unique key of the table. | `text` | | `container_number` | Container number | `text` | | `shipment_id` | Shipment ID associated to the container | `text` | | `shipment_bill_of_lading_number` | Shipment number from the tracking request | `text` | | `shipment_normalized_number` | The normalized version of the shipment number used for querying the carrier | `text` | | `shipment_reference_numbers` | Reference numbers of the shipment, concatenated | `text` | | `container_reference_numbers` | Reference numbers of the container, concatenated | `text` | | `shipment_tags` | Tags added to the shipment, sorted by alphabetical order, concatenated and separated by a comma | `text` | | `customer_id` | Account ID of the customer | `text` | | `customer_name` | Name of the customer | `text` | | `shipping_line_scac` | Standard carrier alpha numeric code of the shipping line | `text` | | `shipping_line_name` | Name of the shipping line | `text` | | `origin_country_code` | Origin country code, populated only if the Empty Out event happens at a different location from the POL | `text` | | `origin_locode` | Origin UN/LOCODE, populated only if the Empty Out event happens at a different location from the POL | `text` | | `origin_city` | Origin city, populated only if the Empty Out event happens at a different location from the POL | `text` | | `origin_timezone` | Origin time zone, populated only if the Empty Out event happens at a different location from the POL | `text` | | `pol_country_code` | Port of Lading country code | `text` | | `pol_locode` | Port of Lading UN/LOCODE | `text` | | `pol_city` | Port of Lading city | `text` | | `pol_timezone` | Port of Lading time zone | `text` | | `pod_country_code` | Port of Discharge country code | `text` | | `pod_locode` | Port of Discharge UN/LOCODE | `text` | | `pod_city` | Port of Discharge city | `text` | | `pod_timezone` | Port of Discharge time zone | `text` | | `pod_terminal_firms_code` | Port of Discharge terminal firms code | `text` | | `pod_terminal_nickname` | Port of Discharge terminal nickname | `text` | | `pod_terminal_name` | Port of Discharge terminal name | `text` | | `destination_country_code` | Destination country code | `text` | | `destination_locode` | Destination UN/LOCODE | `text` | | `destination_city` | Destination city | `text` | | `destination_timezone` | Destination time zone | `text` | | `destination_terminal_firms_code` | Destination terminal firms code | `text` | | `destination_terminal_nickname` | Destination terminal nickname | `text` | | `destination_terminal_name` | Destination terminal name | `text` | | `pol_empty_out_at` | Empty Out, as a UTC timestamp | `timestamp` | | `pol_empty_out_at_local` | Empty Out, as a string in the POL local time zone | `text` | | `pol_full_in_at` | Full In event, as a UTC timestamp | `timestamp` | | `pol_full_in_at_local` | Full In event, as a string in the POL local time zone | `text` | | `origin_rail_loaded_at` | Origin Rail Loaded, as a UTC timestamp | `timestamp` | | `origin_rail_loaded_at_local` | Origin Rail Loaded, as a string in the origin local time zone | `text` | | `origin_rail_departed_at` | Origin Rail Departed, as a UTC timestamp | `timestamp` | | `origin_rail_departed_at_local` | Origin Rail Departed, as a string in the origin local time zone | `text` | | `pol_rail_arrived_at` | Port of Lading Rail Arrived, as a UTC timestamp | `timestamp` | | `pol_rail_arrived_at_local` | Port of Lading Rail Arrived, as a string in the origin local time zone | `text` | | `pol_rail_unloaded_at` | Port of Lading Rail Unloaded, as a UTC timestamp | `timestamp` | | `pol_rail_unloaded_at_local` | Port of Lading Rail Unloaded, as a string in the origin local time zone | `text` | | `pol_loaded_at` | Port of Lading Loaded event, as a UTC timestamp | `timestamp` | | `pol_loaded_at_local` | Port of Lading Loaded event, as a string in the POL local time zone | `text` | | `pol_etd_at` | Port of Lading Estimated Time of Departure, as a UTC timestamp | `timestamp` | | `pol_etd_at_local` | Port of Lading Estimated Time of Departure, as a string in the POL local time zone | `text` | | `pol_atd_at` | Port of Lading Actual Time of Departure, as a UTC timestamp | `timestamp` | | `pol_atd_at_local` | Port of Lading Actual Time of Departure, as a string in the POL local time zone | `text` | | `pod_eta_at` | Port of Discharge Estimated Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_eta_at_local` | Port of Discharge Estimated Time of Arrival, as a string in the POD local time zone | `text` | | `pod_arrived_at` | Port of Discharge Actual Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_arrived_at_local` | Port of Discharge Actual Time of Arrival, as a string in the POD local time zone | `text` | | `pod_berthed_at` | Port of Discharge Berthed event, as a UTC timestamp | `timestamp` | | `pod_berthed_at_local` | Port of Discharge Berthed event, as a string in the POD local time zone | `text` | | `pod_discharged_at` | Port of Discharge Discharged event, as a UTC timestamp | `timestamp` | | `pod_discharged_at_local` | Port of Discharge Discharged event, as a string in the POD local time zone | `text` | | `pod_last_free_day_on` | Current Last Free Day from the POD terminal, as a UTC timestamp | `timestamp` | | `pod_last_free_day_on_local` | Current Last Free Day from the POD terminal, as a string in the POD local time zone | `text` | | `ssl_last_free_day_on` | Current Last Free Day from the shipping line, as a UTC timestamp | `timestamp` | | `ssl_last_free_day_on_local` | Current Last Free Day from the shipping line, as a string in the Destination or POD local time zone | `text` | | `pod_pickup_appointment_at` | Port of Discharge Pickup Appointment, as a UTC timestamp | `timestamp` | | `pod_pickup_appointment_at_local` | Port of Discharge Pickup Appointment, as a string in the POD local time zone | `text` | | `pod_full_out_at` | Port of Discharge Full Out event, as a UTC timestamp | `timestamp` | | `pod_full_out_at_local` | Port of Discharge Full Out event, as a string in the POD local time zone | `text` | | `rail_loaded_at` | First rail loaded after the POD discharge, as a UTC timestamp | `timestamp` | | `rail_loaded_at_local` | First rail loaded after the POD discharge, as a string in the POD local time zone | `text` | | `rail_departed_at` | First rail departure after the POD discharge, as a UTC timestamp | `timestamp` | | `rail_departed_at_local` | First rail departure after the POD discharge, as a string in the POD local time zone | `text` | | `destination_eta_at` | Destination Estimated Time of Arrival, as a UTC timestamp | `timestamp` | | `destination_eta_at_local` | Destination Estimated Time of Arrival, as a string in the Destination local time zone | `text` | | `destination_arrived_at` | Destination Actual Time of Arrival, as a UTC timestamp | `timestamp` | | `destination_arrived_at_local` | Destination Actual Time of Arrival, as a string in the Destination local time zone | `text` | | `rail_unloaded_at` | Destination Rail Unloaded, as a UTC timestamp | `timestamp` | | `rail_unloaded_at_local` | Destination Rail Unloaded, as a string in the Destination local time zone | `text` | | `destination_full_out_at` | Destination Full Out event, as a UTC timestamp | `timestamp` | | `destination_full_out_at_local` | Destination Full Out event, as a string in the Destination local time zone | `text` | | `empty_terminated_at` | Container Empty Returned event, as a UTC timestamp | `timestamp` | | `empty_terminated_at_local` | Container Empty Returned event, as a string in the Destination or POD local time zone | `text` | | `fees_at_pod_terminal` | Current fee amounts, in JSON format. See [hold and fee types](/api-docs/in-depth-guides/holds-and-fees). | `text` | | `demurrage_at_pod_terminal` | Current demurrage amount owed. See [fee types](/api-docs/in-depth-guides/holds-and-fees#fee-types-at-a-glance). | `text` | | `holds_at_pod_terminal` | Current terminal hold statuses, in JSON format. See [hold types](/api-docs/in-depth-guides/holds-and-fees#hold-types-at-a-glance). | `text` | | `freight_hold_at_pod_terminal` | Current freight hold, value is either "Hold", "Pending", or blank | `text` | | `customs_hold_at_pod_terminal` | Current customs hold, value is either "Hold", "Pending", or blank | `text` | | `usda_hold_at_pod_terminal` | Current USDA hold, value is either "Hold", "Pending", or blank | `text` | | `tmf_hold_at_pod_terminal` | Current Traffic Mitigation Fee hold, value is either "Hold", "Pending", or blank | `text` | | `other_hold_at_pod_terminal` | Any other current hold, value is either "Hold", "Pending", or blank | `text` | | `location_at_pod_terminal` | Location at port of discharge terminal | `text` | | `availability_known` | Yes if Terminal49 is receiving availability status from the terminal, No otherwise. | `text` | | `available_for_pickup` | If availability\_known is Yes, then Yes if the container is available to be picked up at terminal, No otherwise | `text` | | `equipment_length` | Length of the container | `integer` | | `equipment_type` | Container type: Dry, Flat Rack, Open Top, Reefer, Tank, unknown | `text` | | `equipment_height` | Container height: High Cube, Standard, unknown | `text` | | `equipment` | Concatenation of the equipment\_length, equipment\_type, and equipment\_height | `text` | | `weight_in_lbs` | Weight of the containre in lbs | `integer` | | `seal_number` | Seal number of the container | `text` | | `pod_full_out_chassis_number` | The chassis number used when container was picked up at POD, if available | `text` | | `pol_voyage_number` | Voyage number of the vessel that departed or will depart from the POL | `text` | | `pol_vessel_name` | Name of the vessel that departed or will depart from the POL | `text` | | `pol_vessel_imo` | IMO of the vessel that departed or will depart from the POL | `text` | | `pod_voyage_number` | Voyage number of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_name` | Name of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_imo` | IMO of the vessel that arrived or will arrive at the POD | `text` | | `terminal_checked_at` | When the terminal was last checked, as a UTC timestamp | `timestamp` | | `line_tracking_last_succeeded_at` | When the shipment information was last refreshed from the shipping line, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_at` | When the tracking of the container stopped, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_reason` | The reason Terminal49 stopped the tracking | `text` | | `created_at` | When the container was added, as a UTC timestamp | `timestamp` | | `updated_at` | When the container was last updated, as a UTC timestamp | `timestamp` | # Containers Source: https://terminal49.com/docs/datasync/table-properties/containers_rail The `containers` table contains 1 row per container (`container_id` is the unique key). Each container is part of 1 shipment (`shipment_id`). This is a large table with denormalized columns to make it easy to use for reporting purposes. For each **event timestamp** there are 2 columns : * a `timestamp` type column in the UTC time zone (Universal Time Coordinated), e.g., `pol_loaded_at`. * a `text` type column in the local time zone of where the event happened, e.g., `pol_loaded_at_local`. The format of the text is : `YYYY-MM-DD HH:MI:SS`. For example `2024-09-24 17:25:00` for 5:25 PM on September 24, 2024. Depending on the event, the time zone applied can be the one from the Port of Lading (`pol_timezone`), the Port of Discharge (`pod_timezone`), or the Inland Destination (`ind_timezone`). *Columns marked with \* are only included with the Intermodal Rail product.* | COLUMN NAME | DESCRIPTION | TYPE | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | `container_id` | Container ID. This is the unique key of the table. | `text` | | `container_number` | Container number | `text` | | `shipment_id` | Shipment ID associated to the container | `text` | | `shipment_bill_of_lading_number` | Shipment number from the tracking request | `text` | | `shipment_normalized_number` | The normalized version of the shipment number used for querying the carrier | `text` | | `shipment_reference_numbers` | Reference numbers of the shipment, concatenated | `text` | | `container_reference_numbers` | Reference numbers of the container, concatenated | `text` | | `shipment_tags` | Tags added to the shipment, sorted by alphabetical order, concatenated and separated by a comma | `text` | | `customer_id` | Account ID of the customer | `text` | | `customer_name` | Name of the customer | `text` | | `shipping_line_scac` | Standard carrier alpha numeric code of the shipping line | `text` | | `shipping_line_name` | Name of the shipping line | `text` | | `pol_country_code` | Port of Lading country code | `text` | | `pol_locode` | Port of Lading UN/LOCODE | `text` | | `pol_city` | Port of Lading city | `text` | | `pol_timezone` | Port of Lading time zone | `text` | | `pod_country_code` | Port of Discharge country code | `text` | | `pod_locode` | Port of Discharge UN/LOCODE | `text` | | `pod_city` | Port of Discharge city | `text` | | `pod_timezone` | Port of Discharge time zone | `text` | | `pod_terminal_firms_code` | Port of Discharge terminal firms code | `text` | | `pod_terminal_nickname` | Port of Discharge terminal nickname | `text` | | `pod_terminal_name` | Port of Discharge terminal name | `text` | | `ind_country_code` | Inland Destination country code | `text` | | `ind_locode` | Inland Destination UN/LOCODE | `text` | | `ind_city` | Inland Destination city | `text` | | `ind_timezone` | Inland Destination time zone | `text` | | `ind_terminal_firms_code` | Inland Destination terminal firms code | `text` | | `ind_terminal_nickname` | Inland Destination terminal nickname | `text` | | `ind_terminal_name` | Inland Destination terminal name | `text` | | `empty_out_at` | Empty Out, as a UTC timestamp | `timestamp` | | `empty_out_at_local` | Empty Out, as a string in the POL local time zone | `text` | | `full_in_at` | Full In event, as a UTC timestamp | `timestamp` | | `full_in_at_local` | Full In event, as a string in the POL local time zone | `text` | | `pol_loaded_at` | Port of Lading Loaded event, as a UTC timestamp | `timestamp` | | `pol_loaded_at_local` | Port of Lading Loaded event, as a string in the POL local time zone | `text` | | `pol_etd_at` | Port of Lading Estimated Time of Departure, as a UTC timestamp | `timestamp` | | `pol_etd_at_local` | Port of Lading Estimated Time of Departure, as a string in the POL local time zone | `text` | | `pol_atd_at` | Port of Lading Actual Time of Departure, as a UTC timestamp | `timestamp` | | `pol_atd_at_local` | Port of Lading Actual Time of Departure, as a string in the POL local time zone | `text` | | `pod_eta_at` | Port of Discharge Estimated Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_eta_at_local` | Port of Discharge Estimated Time of Arrival, as a string in the POD local time zone | `text` | | `pod_arrived_at` | Port of Discharge Actual Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_arrived_at_local` | Port of Discharge Actual Time of Arrival, as a string in the POD local time zone | `text` | | `pod_berthed_at` | Port of Discharge Berthed event, as a UTC timestamp | `timestamp` | | `pod_berthed_at_local` | Port of Discharge Berthed event, as a string in the POD local time zone | `text` | | `pod_discharged_at` | Port of Discharge Discharged event, as a UTC timestamp | `timestamp` | | `pod_discharged_at_local` | Port of Discharge Discharged event, as a string in the POD local time zone | `text` | | `pod_last_free_day_on` | Current Last Free Day from the POD terminal, as a UTC timestamp

Named `pickup_lfd` in the API | `timestamp` | | `pod_last_free_day_on_local` | Current Last Free Day from the POD terminal, as a string in the POD local time zone | `text` | | `ssl_last_free_day_on` | Current Last Free Day from the shipping line, as a UTC timestamp | `timestamp` | | `ssl_last_free_day_on_local` | Current Last Free Day from the shipping line, as a string in the Destination or POD local time zone | `text` | | `pod_pickup_appointment_at` | Port of Discharge Pickup Appointment, as a UTC timestamp

Named `pickup_appointment_at` in the API | `timestamp` | | `pod_pickup_appointment_at_local` | Port of Discharge Pickup Appointment, as a string in the POD local time zone | `text` | | `pod_full_out_at` | Port of Discharge Full Out event, as a UTC timestamp | `timestamp` | | `pod_full_out_at_local` | Port of Discharge Full Out event, as a string in the POD local time zone | `text` | | `pod_rail_carrier_scac`\* | SCAC of the rail carrier at the POD | `text` | | `pod_rail_loaded_at`\* | First rail loaded after the POD discharge, as a UTC timestamp | `timestamp` | | `pod_rail_loaded_at_local`\* | First rail loaded after the POD discharge, as a string in the POD local time zone | `text` | | `pod_rail_departed_at`\* | First rail departure after the POD discharge, as a UTC timestamp | `timestamp` | | `pod_rail_departed_at_local`\* | First rail departure after the POD discharge, as a string in the POD local time zone | `text` | | `ind_rail_carrier_scac`\* | SCAC of the rail carrier at the inland destination | `text` | | `ind_eta_at`\* | Inland Destination Estimated Time of Arrival, as a UTC timestamp | `timestamp` | | `ind_eta_at_local`\* | Inland Destination Estimated Time of Arrival, as a string in the Inland Destination local time zone | `text` | | `ind_arrived_at`\* | Inland Destination Actual Time of Arrival, as a UTC timestamp

Named `ind_ata_at` in the API | `timestamp` | | `ind_arrived_at_local`\* | Inland Destination Actual Time of Arrival, as a string in the Inland Destination local time zone | `text` | | `ind_rail_unloaded_at`\* | Inland Destination Rail Unloaded, as a UTC timestamp | `timestamp` | | `ind_rail_unloaded_at_local`\* | Inland Destination Rail Unloaded, as a string in the Inland Destination local time zone | `text` | | `ind_last_free_day_on`\* | Last Free Day at the inland destination facility from the rail carrier, as a UTC timestamp

Named `ind_facility_lfd_on` in the API | `timestamp` | | `ind_last_free_day_on_local`\* | Last Free Day at the inland destination facility from the rail carrier, as a string in the inland estination local time zone | `text` | | `ind_full_out_at` | Inland Destination Full Out event, as a UTC timestamp

Named `final_destination_full_out_at` in the API | `timestamp` | | `ind_full_out_at_local` | Inland Destination Full Out event, as a string in the Inland Destination local time zone | `text` | | `empty_terminated_at` | Container Empty Returned event, as a UTC timestamp | `timestamp` | | `empty_terminated_at_local` | Container Empty Returned event, as a string in the Destination or POD local time zone | `text` | | `fees_at_pod_terminal` | Current fee amounts at the POD terminal, in JSON format. See [hold and fee types](/api-docs/in-depth-guides/holds-and-fees). | `text` | | `demurrage_at_pod_terminal` | Current demurrage amount owed at the POD terminal. See [fee types](/api-docs/in-depth-guides/holds-and-fees#fee-types-at-a-glance). | `text` | | `holds_at_pod_terminal` | Current terminal hold statuses at the POD, in JSON format. See [hold types](/api-docs/in-depth-guides/holds-and-fees#hold-types-at-a-glance). | `text` | | `freight_hold_at_pod_terminal` | Current freight hold at the POD terminal, value is either "Hold", "Pending", or blank | `text` | | `customs_hold_at_pod_terminal` | Current customs hold at the POD terminal, value is either "Hold", "Pending", or blank | `text` | | `usda_hold_at_pod_terminal` | Current USDA hold at the POD terminal, value is either "Hold", "Pending", or blank | `text` | | `tmf_hold_at_pod_terminal` | Current Traffic Mitigation Fee hold at the POD terminal, value is either "Hold", "Pending", or blank | `text` | | `other_hold_at_pod_terminal` | Any other current hold at the POD terminal, value is either "Hold", "Pending", or blank | `text` | | `location_at_pod_terminal` | Location at the port of discharge terminal | `text` | | `availability_known` | Yes if Terminal49 is receiving availability status from the POD terminal, No otherwise. | `text` | | `available_for_pickup` | If availability\_known is Yes, then Yes if the container is available to be picked up at the POD terminal, No otherwise | `text` | | `equipment_length` | Length of the container | `integer` | | `equipment_type` | Container type: Dry, Flat Rack, Open Top, Reefer, Tank, unknown | `text` | | `equipment_height` | Container height: High Cube, Standard, unknown | `text` | | `equipment` | Concatenation of the equipment\_length, equipment\_type, and equipment\_height | `text` | | `weight_in_lbs` | Weight of the containre in lbs | `integer` | | `seal_number` | Seal number of the container | `text` | | `pod_full_out_chassis_number` | The chassis number used when container was picked up at POD, if available | `text` | | `pod_voyage_number` | Voyage number of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_name` | Name of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_imo` | IMO of the vessel that arrived or will arrive at the POD | `text` | | `terminal_checked_at` | When the POD terminal was last checked, as a UTC timestamp | `timestamp` | | `line_tracking_last_succeeded_at` | When the shipment information was last refreshed from the shipping line, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_at` | When the tracking of the container stopped, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_reason` | The reason Terminal49 stopped the tracking | `text` | | `created_at` | When the container was added, as a UTC timestamp | `timestamp` | | `updated_at` | When the container was last updated, as a UTC timestamp | `timestamp` | # Shipments Source: https://terminal49.com/docs/datasync/table-properties/shipments The `shipments` table contains 1 row per shipment (`shipment_id` is the unique key). A shipment contains 1 or more containers. | COLUMN NAME | DESCRIPTION | TYPE | | --------------------------------- | ----------------------------------------------------------------------------------------------- | ----------- | | `shipment_id` | Shipment ID. This is the unique key of the table. | `text` | | `shipping_line_scac` | Standard carrier alpha numeric code of the shipping line | `text` | | `shipping_line_name` | Name of the shipping line | `text` | | `bill_of_lading_number` | Shipment number from the tracking request | `text` | | `normalized_number` | The normalized version of the shipment number used for querying the carrier | `text` | | `reference_numbers` | Reference numbers of the shipment, contatenated | `text` | | `tags` | Tags added to the shipment, sorted by alphabetical order, concatenated and separated by a comma | `text` | | `customer_id` | Account ID of the customer | `text` | | `customer_name` | Name of the customer | `text` | | `pol_locode` | Port of Lading UN/LOCODE | `text` | | `pod_locode` | Port of Discharge UN/LOCODE | `text` | | `pod_terminal_firms_code` | Port of Discharge terminal firms code | `text` | | `destination_locode` | Destination UN/LOCODE | `text` | | `destination_terminal_firms_code` | Destination terminal firms code | `text` | | `pol_atd_at` | Port of Lading Actual Time of Departure, as a UTC timestamp | `timestamp` | | `pol_etd_at` | Port of Lading Estimated Time of Departure, as a UTC timestamp | `timestamp` | | `pod_eta_at` | Port of Discharge Estimated Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_arrived_at` | Port of Discharge Actual Time of Arrival, as a UTC timestamp | `timestamp` | | `pod_voyage_number` | Voyage number of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_name` | Name of the vessel that arrived or will arrive at the POD | `text` | | `pod_vessel_imo` | IMO of the vessel that arrived or will arrive at the POD | `text` | | `line_tracking_last_succeeded_at` | When the shipment information was last refreshed from the shipping line, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_at` | When the tracking of the shipment stopped, as a UTC timestamp | `timestamp` | | `line_tracking_stopped_reason` | Reason why the tracking of the shipment stopped | `text` | | `created_at` | When the shipment was added, as a UTC timestamp | `timestamp` | | `updated_at` | When the shipment was last updated, as a UTC timestamp | `timestamp` | # Tracking Requests Source: https://terminal49.com/docs/datasync/table-properties/tracking-requests The `tracking_requests` table contains 1 row per tracking request (`tracking_request_id`is the unique key). A tracking request can fail or succeed (`status` column). A successful tracking request will lead to the creation of a shipment (`shipment_id`). There can be multiple tracking requests for the same requested number (possibly failing before finally succeeding). | COLUMN NAME | DESCRIPTION | TYPE | | --------------------- | ----------------------------------------------------------------------------------------------- | ----------- | | `tracking_request_id` | Tracking request ID. This is the unique key of the table. | `text` | | `request_number` | Number requested to be tracked | `text` | | `reference_numbers` | Reference numbers associated to the tracking request, concatenated | `text` | | `shipment_tags` | Tags added to the request, concatenated and separated by a comma | `text` | | `status` | Status of the tracking request: created, pending, awaiting\_manifest, failed, tracking\_stopped | `text` | | `failed_reason` | For tracking requests that failed, a description of the error | `text` | | `request_type` | Type of tracking request: bill\_of\_lading, booking\_number, or container | `text` | | `scac` | Standard carrier alpha numeric code of the shipping line | `text` | | `shipment_id` | If the tracking request succeeded, this is the ID of the shipment that was created | `text` | | `created_at` | When the tracking was requested, as a UTC timestamp | `timestamp` | | `updated_at` | When the tracking request was last updated, as a UTC timestamp | `timestamp` | # Transfer Status Source: https://terminal49.com/docs/datasync/table-properties/transfer-status The `_transfer_status` is an additional technical table that identifies when each table was last updated by DataSync. | COLUMN NAME | DESCRIPTION | TYPE | | -------------------------- | ------------------------------------------------- | ----------- | | `data_model_name` | Name of the table | `text` | | `transfer_last_updated_at` | When the latest sync happened, as a UTC timestamp | `timestamp` | # Transport Events Source: https://terminal49.com/docs/datasync/table-properties/transport-events The `transport_events` table contains 1 row per event (`id`is the unique key). An event is associated to a specific container (`container_id` is the foreign key). An event is a specific milestone in the container lifecycle: for example, when the container was loaded at the Port of Lading, or when the vessel arrived at the Port of Discharge. These events are provided as columns in the `containers` DataSync table, and as rows here in the `transport_events` table. You can use one or the other based on what is most practical for you. The `transport_events` table includes the transshipment events, which are not part of the `containers` table columns. This table does not provide any estimated future events. *The `transport_events` table is currently only provided to DataSync customers who request it.* *Rail events from the POD to the inland destination are only provided in the Intermodal Rail product : rail\_loaded, rail\_departed, rail\_arrived, arrived\_at\_inland\_destination, rail\_unloaded, pickup\_lfd.changed.* | COLUMN NAME | DESCRIPTION | TYPE | | ------------------------- | ------------------------------------------------------------------------------------------------- | ----------- | | `id` | Transport Event ID. This is the unique key of the table. | `text` | | `event` | Name of the transport event. For example: container.transport.vessel\_departed | `text` | | `event_timestamp` | When the event happened, as a UTC timestamp | `timestamp` | | `event_timestamp_local` | When the event happened, as a string in the local time zone | `text` | | `container_id` | ID of the container the event is associated to | `text` | | `container_number` | Number of the container the event is associated to | `text` | | `shipment_id` | ID of the shipment the event is associated to | `text` | | `shipment_number` | Number of the shipment the event is associated to | `text` | | `port_metro_id` | ID of the location where the event happened | `text` | | `port_metro_locode` | Locode of the location where the event happened | `text` | | `port_metro_country_code` | Country code of the location where the event happened | `text` | | `port_metro_city` | Name of the location where the event happened | `text` | | `port_metro_time_zone` | Name of the time zone where the event happened | `text` | | `facility_id` | ID of the facility (terminal) where the event happened | `text` | | `facility_firms_code` | Firms code of the facility (terminal) where the event happened | `text` | | `facility_nickname` | Nickname of the facility (terminal) where the event happened | `text` | | `facility_name` | Name of the facility (terminal) where the event happened | `text` | | `vessel_id` | ID of the vessel associated to the event | `text` | | `vessel_name` | Name of the vessel associated to the event | `text` | | `vessel_imo` | IMO of the vessel associated to the event | `text` | | `vessel_mmsi` | MMSI of the vessel associated to the event | `text` | | `voyage_number` | Voyage number associated to the event | `text` | | `data_source_label` | Data source of the event: shipping\_line, terminal, ais, rail, t49\_operations\_team, user\_input | `text` | | `invalidated_at` | When the event was marked as invalid, as a UTC timestamp | `timestamp` | | `invalidation_reason` | Reason why the event was marked as invalid | `text` | | `previous_version_id` | If the event replaces an invalidated event, this is the ID of the invalidated event | `text` | | `created_at` | When the event was originally added, as a UTC timestamp | `timestamp` | | `updated_at` | When the event was updated, as a UTC timestamp | `timestamp` | # Terminal49 Dev Documentation Source: https://terminal49.com/docs/home We offer two fantastic ways to track your shipments from origin to destination. 1. [Terminal49 DataSync](/datasync/overview). Get tables full of fresh information delivered into your current data system. Easy to set up, and perfect for complementing your current data. 2. [Terminal49 API](/api-docs/getting-started/start-here). Connect directly with the API, pull data for specific shipments and containers, and get updates via webhooks. If you already have a data store that feeds the rest of your system, DataSync is probably what you want. ## What can I use Terminal49 data for? Here are just a few of the data points we return and possible use-cases. | DATA | EXAMPLE USE CASE | | -------------------------------------- | ------------------------------------------------------------------------ | | Destination ETA | Surface ETA changes to your relevant teams as they're reported | | Last Free Day and terminal statusΒΉ | Track containers approaching LFD and prioritize dispatching | | Fees and holds at destination terminal | Clear your cargo to keep you containers moving | | Actual departure and arrival times | Report journey times by route to compare your ocean carriers performance | *1. At container ports in the US* ## How it works All you need to provide are your BOL numbers and SCACs. Terminal 49 will lookup the shipment with the carrier and populate shipment details including containers. **Don't know your SCAC?** Our [Auto-Detect Carrier](/api-docs/in-depth-guides/auto-detect-carrier) API can identify it automatically from your tracking number. Once the shipment is set up, Terminal 49 periodically checks with the carrier and the destination terminal. If any of the details of your shipment or containers change (for example - if the ETA changes) we'll ensure you're always kept up to date. * If you're using DataSync, we'll update the data in your system * If you're using the API, we'll post the shipment to the the webhook you provide πŸ‘ˆπŸ½ Please click API Docs or Data Sync on the left to get started! # MCP Overview Source: https://terminal49.com/docs/mcp/home Terminal49 MCP server for AI-powered container tracking # Terminal49 MCP Server Use the Terminal49 MCP server to let Claude or Cursor answer questions with live container and shipment dataβ€”without writing custom glue code. ## TL;DR – Get Started in 5 Minutes Go to the [Terminal49 dashboard](https://app.terminal49.com/developers/api-keys) β†’ Settings β†’ API Tokens and create a `T49_API_TOKEN`. * **Claude Desktop** (macOS / Windows / Linux) * **Cursor IDE** Edit `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ```json theme={null} { "mcp": { "servers": { "terminal49": { "url": "https://mcp.terminal49.com/mcp", "headers": { "Authorization": "Bearer " } } } } } ``` > "Using the Terminal49 MCP server, track container CAIU1234567 with Maersk." Ask Claude: > "List the tools available in the Terminal49 MCP server and what they're for." Need test container numbers? See [Test Numbers](/api-docs/useful-info/test-numbers) for containers you can use during development. For the full walkthrough (including local stdio dev, deployment, and SDK examples), see [MCP Server Quickstart](/api-docs/in-depth-guides/mcp). *** ## Transports | Transport | Endpoint | Best For | | ----------------- | ------------------------------ | -------------------------------- | | HTTP (streamable) | `POST /api/mcp` or `POST /mcp` | Serverless, short-lived requests | **Authentication**: * API token only (OAuth not required for this release) * Header: `Authorization: Bearer ` or `Authorization: Token ` * Or set `T49_API_TOKEN` environment variable when self-hosting Claude Desktop and Cursor use the HTTP transport at `https://mcp.terminal49.com/mcp`. Planning OAuth for hosted MCP? Use the [Hosted HTTP OAuth Requirements](/mcp/hosted-http-oauth-requirements) and [Hosted HTTP OAuth Test Plan](/mcp/hosted-http-oauth-test-plan). The same [rate limits](/api-docs/in-depth-guides/rate-limiting) apply to MCP endpoints as the REST API. *** ## Tools Reference ### `search_container` Find containers by container number, BL, booking, or your own reference. This is the fastest way to locate containers. **Parameters** * `query` *(string, required)* – container number, BL, booking, or reference ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "search_container", "arguments": { "query": "CAIU1234567" } } } ``` ```json theme={null} { "containers": [ { "id": "abc-123-uuid", "containerNumber": "CAIU1234567", "status": "in_transit", "shippingLine": "Maersk", "podTerminal": "APM Terminals", "destination": "Los Angeles" } ], "shipments": [], "totalResults": 1 } ``` **Good for** * "Find this container and tell me where it is" * "Show all containers with reference PO-12345" **REST equivalent**: [GET /containers](/api-docs/api-reference/containers/list-containers) with filters *** ### `track_container` Start tracking a new container. Creates a tracking request and returns container details. **Parameters** * `number` *(string, required)* – container number, BL, or booking number * `numberType` *(string, optional)* – override inference (`container`, `bill_of_lading`, `booking_number`) * `scac` *(string, optional)* – shipping line code, e.g., `MAEU` for Maersk * `refNumbers` *(string\[], optional)* – your reference numbers ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "track_container", "arguments": { "number": "CAIU1234567", "scac": "MAEU" } } } ``` **Good for** * "Track container CAIU1234567 with Maersk" * "Start tracking this new shipment" **REST equivalent**: [POST /tracking\_requests](/api-docs/api-reference/tracking-requests/create-a-tracking-request) *** ### `get_container` Get detailed container information with flexible data loading. Choose what to include based on your question. **Parameters** * `id` *(uuid, required)* – Terminal49 container UUID * `include` *(string\[], optional)* – what to load: * `shipment` – routing, BOL, line, ref numbers (lightweight) * `pod_terminal` – terminal name, location (lightweight) * `transport_events` – full event history (heavy, 50-100 events) ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_container", "arguments": { "id": "abc-123-uuid", "include": ["shipment", "pod_terminal"] } } } ``` ```json theme={null} { "id": "abc-123-uuid", "number": "CAIU1234567", "status": "available_for_pickup", "equipment": { "type": "40HC", "length": "40", "height": "high_cube" }, "location": { "currentLocation": "APM Terminals", "availableForPickup": true, "podArrivedAt": "2025-01-15T08:30:00Z", "podDischargedAt": "2025-01-16T14:20:00Z" }, "demurrage": { "pickupLfd": "2025-01-22", "holds": [], "fees": [] }, "shipment": { "id": "shipment-uuid", "billOfLading": "MAEU123456789", "shippingLineScac": "MAEU" } } ``` **Good for** * "What's the status of this container?" * "Is it available for pickup? Any holds?" * "When does demurrage start?" **REST equivalent**: [GET /containers/](/api-docs/api-reference/containers/get-a-container) *** ### `get_container_transport_events` Get the full event timeline for a container's journey. **Parameters** * `id` *(uuid, required)* – Terminal49 container UUID ```json theme={null} { "totalEvents": 47, "eventCategories": { "vesselEvents": 8, "railEvents": 12, "terminalEvents": 18 }, "milestones": { "vesselLoadedAt": "2024-12-08T10:30:00Z", "vesselDepartedAt": "2024-12-09T14:00:00Z", "vesselArrivedAt": "2024-12-22T08:30:00Z", "dischargedAt": "2024-12-23T11:15:00Z" }, "timeline": [ { "event": "container.transport.vessel_loaded", "timestamp": "2024-12-08T10:30:00Z", "location": { "name": "Shanghai", "locode": "CNSHA" } } ] } ``` **Good for** * "Show me the journey timeline" * "What happened to this container?" * "How long was the rail portion?" **REST equivalent**: [GET /containers//transport\_events](/api-docs/api-reference/containers/get-a-containers-transport-events) *** ### `get_shipment_details` Get shipment-level information including routing, BOL, and all containers. **Parameters** * `id` *(uuid, required)* – Terminal49 shipment UUID * `include_containers` *(boolean, optional)* – include container list (default: true) **Good for** * "Tell me about this shipment" * "What containers are on this BL?" * "Show me the routing" **REST equivalent**: [GET /shipments/](/api-docs/api-reference/shipments/get-a-shipment) *** ### `get_supported_shipping_lines` List carriers supported by Terminal49 with their SCAC codes. **Parameters** * `search` *(string, optional)* – filter by name or SCAC **Good for** * "What carriers do you support?" * "What's the SCAC code for CMA CGM?" **REST equivalent**: [GET /shipping\_lines](/api-docs/api-reference/shipping-lines/shipping-lines) *** ### `get_container_route` Get detailed multi-leg routing with vessel itinerary. This is a **paid feature**. If not enabled for your account, use `get_container_transport_events` for historical movement data instead. **Parameters** * `id` *(uuid, required)* – Terminal49 container UUID **Good for** * "What's the routing for this container?" * "Which transshipment ports?" * "What vessel is it on?" **REST equivalent**: [GET /containers//route](/api-docs/api-reference/containers/get-container-route) *** ### `list_shipments` List shipments with optional filters and pagination. **Parameters** * `status`, `port`, `carrier`, `updated_after` *(string, optional)* * `include_containers` *(boolean, optional)* * `page`, `page_size` *(number, optional)* **Good for** * "List recent shipments" * "Show in-transit shipments for MAEU" **REST equivalent**: [GET /shipments](/api-docs/api-reference/shipments/list-shipments) *** ### `list_containers` List containers with optional filters and pagination. **Parameters** * `status`, `port`, `carrier`, `updated_after` *(string, optional)* * `include` *(string, optional)* – comma-separated include list * `page`, `page_size` *(number, optional)* **Good for** * "List containers updated in the last 24h" * "Show containers at a specific POD port" **REST equivalent**: [GET /containers](/api-docs/api-reference/containers/list-containers) *** ### `list_tracking_requests` List tracking requests with optional filters and pagination. **Parameters** * `filters` *(object, optional)* – raw query filters * `page`, `page_size` *(number, optional)* **Good for** * "Show failed tracking requests" * "List latest tracking activity" **REST equivalent**: [GET /tracking\_requests](/api-docs/api-reference/tracking-requests/list-tracking-requests) *** ## Prompts Reference Prompts are pre-built workflows that guide the AI through multi-step analysis. ### `track-shipment` Quick container tracking with optional carrier specification. **Arguments** * `container_number` *(string, required)* – e.g., `CAIU1234567` * `carrier` *(string, optional)* – SCAC code, e.g., `MAEU` **Try this in Claude:** > "Using Terminal49, track container CAIU1234567 and show me its current status, location, and ETA." *** ### `check-demurrage` Analyze demurrage/detention risk for a container. **Arguments** * `container_id` *(uuid, required)* – from `search_container` or `get_container` **Try this in Claude:** > "Using Terminal49, check demurrage risk for container CAIU1234567 and explain which fees apply and when." *** ### `analyze-delays` Identify delays and root causes in a container's journey. **Arguments** * `container_id` *(uuid, required)* – Container UUID **Try this in Claude:** > "Using Terminal49, analyze delays for container CAIU1234567 and tell me what caused them." *** ## Resources Reference Resources provide static or dynamic data that AI clients can read. | Resource URI | Description | | -------------------------------------- | --------------------------------------- | | `terminal49://container/{id}` | Container data in markdown format | | `terminal49://docs/milestone-glossary` | Event/milestone reference documentation | ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "resources/read", "params": { "uri": "terminal49://docs/milestone-glossary" } } ``` *** ## Not Yet Supported These Terminal49 API capabilities are available via the [SDK](/api-docs/in-depth-guides/mcp#sdk-usage) but not yet exposed as MCP tools: | API | Description | Workaround | | ------------------- | -------------------------------- | ------------------------------------------------------------------------------ | | `update_shipment` | Update shipment ref numbers/tags | Use [REST API](/api-docs/api-reference/shipments/edit-a-shipment) | | `stop_tracking` | Stop tracking a shipment | Use [REST API](/api-docs/api-reference/shipments/stop-tracking-shipment) | | `resume_tracking` | Resume tracking a shipment | Use [REST API](/api-docs/api-reference/shipments/resume-tracking-shipment) | | `raw_events` | Get raw EDI event data | Use [REST API](/api-docs/api-reference/containers/get-a-containers-raw-events) | | `refresh_container` | Force refresh container data | Use [REST API](/api-docs/api-reference/containers/refresh-container) | | Webhooks | Real-time event notifications | Configure via [dashboard](/api-docs/in-depth-guides/webhooks) | Shipment/container list operations are available via MCP. Update/stop/resume tracking operations still require REST API or direct SDK usage. *** ## Related Guides * [MCP Server Quickstart](/api-docs/in-depth-guides/mcp) – Full setup, local dev, deployment * [Rate Limiting](/api-docs/in-depth-guides/rate-limiting) – Same limits apply to MCP * [Test Numbers](/api-docs/useful-info/test-numbers) – Containers for testing * [Webhooks](/api-docs/in-depth-guides/webhooks) – Real-time updates (use with MCP for best results) # Error Handling Source: https://terminal49.com/docs/sdk/error-handling Catch and handle errors from the Terminal49 SDK The SDK throws typed errors you can catch and handle based on the error type. ## Error types | Error | Cause | | ------------------------ | ------------------------------------------ | | `AuthenticationError` | Invalid or missing API token | | `AuthorizationError` | Valid token but insufficient permissions | | `NotFoundError` | Resource doesn't exist or isn't accessible | | `ValidationError` | Invalid request parameters | | `RateLimitError` | Too many requests | | `FeatureNotEnabledError` | Feature requires a plan upgrade | | `UpstreamError` | Carrier or terminal API is unavailable | | `Terminal49Error` | Generic error fallback | ## Basic error handling ```typescript theme={null} import { Terminal49Client, AuthenticationError, RateLimitError, NotFoundError, } from '@terminal49/sdk'; const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, }); try { await client.containers.get('container-uuid'); } catch (error) { if (error instanceof AuthenticationError) { console.error('Invalid API token'); } else if (error instanceof NotFoundError) { console.error('Container not found'); } else if (error instanceof RateLimitError) { console.error('Rate limited, retrying in 60s'); await new Promise((resolve) => setTimeout(resolve, 60000)); } else { throw error; } } ``` ## Automatic retries The SDK automatically retries `429` and `5xx` responses with exponential backoff up to `maxRetries` (default: 2). ```typescript theme={null} const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, maxRetries: 3, }); ``` ## Error properties All SDK errors include: | Property | Type | Description | | --------- | ------- | -------------------------------- | | `message` | string | Human-readable error description | | `status` | number | HTTP status code | | `details` | unknown | Raw error payload from the API | # Filtering & Pagination Source: https://terminal49.com/docs/sdk/filtering-pagination Query shipments and containers with filters and handle large result sets ## Filtering shipments Pass filter parameters to narrow results: ```typescript theme={null} const shipments = await client.shipments.list({ status: 'in_transit', port: 'USLAX', carrier: 'MAEU', updatedAfter: '2025-01-01T00:00:00Z', }); ``` Available shipment filters: | Filter | Type | Description | | ------------------- | -------- | ----------------------------------------------------------------- | | `status` | string | Shipment status (for example `in_transit` or `delivered`) | | `port` | string | UN/LOCODE for port of discharge | | `carrier` | string | SCAC code (for example `MAEU`, `HLCU`) | | `updatedAfter` | ISO 8601 | Only shipments updated after this timestamp | | `includeContainers` | boolean | Set to `false` to omit containers from the included relationships | ## Filtering containers ```typescript theme={null} const containers = await client.containers.list({ status: 'discharged', port: 'USLAX', carrier: 'MAEU', updatedAfter: '2025-01-01T00:00:00Z', include: 'shipment,pod_terminal', }); ``` Available container filters: | Filter | Type | Description | | -------------- | -------- | ---------------------------------------------------- | | `status` | string | Container status | | `port` | string | UN/LOCODE for port of discharge | | `carrier` | string | SCAC code | | `updatedAfter` | ISO 8601 | Only containers updated after this timestamp | | `include` | string | Comma-delimited list of related resources to include | For list endpoints, avoid heavy `include` usage for performance. When you need deep relationships, prefer single-resource endpoints like `containers.get` or `shipments.get`. ## Pagination List methods accept pagination options with `page` and `pageSize` (page numbers are 1-based): ```typescript theme={null} const page1 = await client.shipments.list({}, { page: 1, pageSize: 25, format: 'mapped', }); const page2 = await client.shipments.list({}, { page: 2, pageSize: 25, format: 'mapped', }); ``` When using `format: 'mapped'`, list results include `items`, `links`, and `meta`. When using `format: 'raw'`, these live in the JSON:API response. ## Common patterns ### Recently updated shipments ```typescript theme={null} const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(); const updated = await client.shipments.list({ updatedAfter: oneDayAgo, }); ``` ### In-transit containers at a specific port ```typescript theme={null} const containers = await client.containers.list({ status: 'in_transit', port: 'USLAX', }); ``` # Introduction Source: https://terminal49.com/docs/sdk/introduction TypeScript SDK for the Terminal49 API The Terminal49 TypeScript SDK lets you track containers, retrieve shipment data, and receive status updates from your Node.js applications. ## Requirements * Node.js 18 or later * A Terminal49 API key ([get one here](https://app.terminal49.com/developers)) ## Install ```bash theme={null} npm install @terminal49/sdk ``` ## Setup Store your API key as an environment variable: ```bash theme={null} export T49_API_TOKEN=your_api_key ``` Then initialize the client: ```typescript theme={null} import { Terminal49Client } from '@terminal49/sdk'; const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, }); ``` ## What you can do * **Track containers** β€” Create tracking requests by container number, booking number, or bill of lading * **List shipments and containers** β€” Query with filters by status, port, carrier, or date * **Get transport events** β€” Pull milestones, timestamps, and location updates * **Fetch routing details** β€” See the full journey including vessels and ports For real-time updates, set up [webhooks](/api-docs/in-depth-guides/webhooks) to receive status changes as they happen. ## Next steps Track your first container in 5 minutes See all available SDK methods # Methods Reference Source: https://terminal49.com/docs/sdk/methods All available methods in the Terminal49 SDK The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each method corresponds to an [API endpoint](/api-docs/home). ## Resource namespaces (recommended) ### Search | Method | Description | | ---------------------- | ----------------------------------------------------------------------- | | `client.search(query)` | Search across shipments and containers by number, reference, or keyword | ### Shipments | Method | Description | | -------------------------------------------------------- | --------------------------------------------------------------------------------------- | | `client.shipments.get(id, includeContainers?, options?)` | Fetch a shipment by ID. Set `includeContainers: false` to omit container relationships. | | `client.shipments.list(filters?, options?)` | List shipments matching filter criteria. | | `client.shipments.update(id, attrs, options?)` | Update shipment attributes like reference numbers or tags. | | `client.shipments.stopTracking(id, options?)` | Stop tracking a shipment and its containers. | | `client.shipments.resumeTracking(id, options?)` | Resume tracking a previously stopped shipment. | ### Containers | Method | Description | | ----------------------------------------------- | -------------------------------------------------------------------- | | `client.containers.get(id, include?, options?)` | Fetch a container by ID. `include` is an array of related resources. | | `client.containers.list(filters?, options?)` | List containers matching filter criteria. | | `client.containers.events(id, options?)` | Get transport events for a container. | | `client.containers.route(id, options?)` | Get routing details: vessels, ports, and journey legs. | | `client.containers.rawEvents(id, options?)` | Get unprocessed events as received from carriers. | | `client.containers.refresh(id, options?)` | Request an immediate data refresh from the carrier. | ### Tracking Requests | Method | Description | | ----------------------------------------------------------- | ------------------------------------------------------------------- | | `client.trackingRequests.list(filters?, options?)` | List tracking requests. | | `client.trackingRequests.get(id, options?)` | Fetch a single tracking request. | | `client.trackingRequests.update(id, attrs, options?)` | Update tracking request attributes. | | `client.trackingRequests.create(params)` | Create a tracking request with an explicit request type and SCAC. | | `client.trackingRequests.inferNumber(number)` | Detect whether a number is a container, booking, or bill of lading. | | `client.trackingRequests.createFromInfer(number, options?)` | Create a tracking request with automatic number type detection. | ### Shipping Lines | Method | Description | | ---------------------------------------------- | ------------------------------------------------------ | | `client.shippingLines.list(search?, options?)` | List carriers. Use `search` to filter by name or SCAC. | ## Helpers and aliases | Method | Description | | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `client.trackContainer(params)` | Convenience helper that creates a tracking request using a container or booking number. | | `client.listTrackRequests(filters?, options?)` | Alias for `client.trackingRequests.list`. | | `client.getDemurrage(containerId)` | Returns a subset of demurrage-related fields for a container. See [holds, fees, and release readiness](/api-docs/in-depth-guides/holds-and-fees) for context. | | `client.getRailMilestones(containerId)` | Returns rail milestones derived from transport events. | | `client.deserialize(document)` | Deserialize a JSON:API document into plain objects using JSONA. | ## Direct method equivalents All namespace methods are also available as direct methods on the client: | Namespace method | Direct method | | ----------------------------------------- | --------------------------------------- | | `client.shipments.get` | `client.getShipment` | | `client.shipments.list` | `client.listShipments` | | `client.shipments.update` | `client.updateShipment` | | `client.shipments.stopTracking` | `client.stopTrackingShipment` | | `client.shipments.resumeTracking` | `client.resumeTrackingShipment` | | `client.containers.get` | `client.getContainer` | | `client.containers.list` | `client.listContainers` | | `client.containers.events` | `client.getContainerTransportEvents` | | `client.containers.route` | `client.getContainerRoute` | | `client.containers.rawEvents` | `client.getContainerRawEvents` | | `client.containers.refresh` | `client.refreshContainer` | | `client.trackingRequests.list` | `client.listTrackingRequests` | | `client.trackingRequests.get` | `client.getTrackingRequest` | | `client.trackingRequests.update` | `client.updateTrackingRequest` | | `client.trackingRequests.create` | `client.createTrackingRequest` | | `client.trackingRequests.inferNumber` | `client.inferTrackingNumber` | | `client.trackingRequests.createFromInfer` | `client.createTrackingRequestFromInfer` | | `client.shippingLines.list` | `client.listShippingLines` | ## Common options Most methods accept an `options` object with `format`: ```typescript theme={null} const shipment = await client.shipments.get('shipment-id', true, { format: 'mapped', }); ``` Supported formats: * `raw` (default) returns the JSON:API response * `mapped` returns simplified objects for methods that support mapping * `both` returns `{ raw, mapped }` You can set a default format when initializing the client: ```typescript theme={null} const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, defaultFormat: 'mapped', }); ``` List methods also accept pagination options: ```typescript theme={null} const shipments = await client.shipments.list({}, { page: 1, pageSize: 25, format: 'mapped', }); ``` See [Filtering & Pagination](/sdk/filtering-pagination) for details. # Quickstart Source: https://terminal49.com/docs/sdk/quickstart Track a container and retrieve shipment data in 5 minutes This walkthrough shows the most common SDK operations: creating a tracking request, listing shipments, and fetching container details. ## Prerequisites Make sure you have [installed the SDK](/sdk/introduction) and set your `T49_API_TOKEN` environment variable. ## Complete example ```typescript theme={null} import { Terminal49Client } from '@terminal49/sdk'; const client = new Terminal49Client({ apiToken: process.env.T49_API_TOKEN!, }); async function main() { // 1) Track a container (creates a tracking request) // Provide a SCAC for faster, more reliable inference when known. await client.trackingRequests.createFromInfer('MSCU1234567', { scac: 'MSCU', }); // 2) List your shipments (mapped response) const shipments = await client.shipments.list( { updatedAfter: '2025-01-01T00:00:00Z' }, { format: 'mapped' }, ); console.log(`Found ${shipments.items.length} shipments`); // 3) Get a specific container with related data (raw JSON:API) const containerId = 'your-container-uuid'; const container = await client.containers.get(containerId, [ 'shipment', 'pod_terminal', ]); console.log(container.data?.id); // 4) Get transport events (milestones and timeline) const events = await client.containers.events(containerId, { format: 'mapped', }); console.log(`Container has ${events.length} events`); // 5) Get routing details (vessels, ports, legs) const route = await client.containers.route(containerId, { format: 'mapped', }); console.log(`Route has ${route.locations.length} locations`); } main(); ``` ## What’s happening **Tracking requests** tell Terminal49 to start monitoring a container. You can track by container number, booking number, or bill of lading. Once tracked, Terminal49 polls carriers and terminals for updates. **Shipments** are the parent objects that group related containers. A single bill of lading might have multiple containers. **Events** are individual milestones: gate out, vessel departure, discharge, and more. Each event has a timestamp, location, and description. **Routes** show the planned and actual journey, broken into locations with inbound and outbound legs. ## Next steps * [Methods Reference](/sdk/methods) β€” See all available operations * [Filtering & Pagination](/sdk/filtering-pagination) β€” Query large datasets efficiently * [Webhooks](/api-docs/in-depth-guides/webhooks) β€” Get notified when shipments update # Authentication Source: https://terminal49.com/docs/sdk/typescript/authentication This page has moved. * [SDK Introduction](/sdk/introduction) # Available Methods Source: https://terminal49.com/docs/sdk/typescript/available-methods This page has moved. * [Methods Reference](/sdk/methods) # Error Handling Source: https://terminal49.com/docs/sdk/typescript/error-handling This page has moved. * [Error Handling](/sdk/error-handling) # Filtering Source: https://terminal49.com/docs/sdk/typescript/filtering This page has moved. * [Filtering & Pagination](/sdk/filtering-pagination) # TypeScript Installation Source: https://terminal49.com/docs/sdk/typescript/installation This page has moved. * [SDK Introduction](/sdk/introduction) # Pagination Source: https://terminal49.com/docs/sdk/typescript/pagination This page has moved. * [Filtering & Pagination](/sdk/filtering-pagination) # Quickstart Source: https://terminal49.com/docs/sdk/typescript/quickstart This page has moved. * [SDK Quickstart](/sdk/quickstart) # API & DataSync Updates Source: https://terminal49.com/docs/updates/home Release notes for Terminal49 API and DataSync. This page contains updates to **Terminal49 API** and **DataSync** only (not general product updates). ### Container Holds, Fees, and Release Readiness Published a comprehensive guide for working with holds and fees data in the Terminal49 API. The guide covers: * **Pickup readiness logic** β€” a decision flowchart and code example showing how to combine `available_for_pickup` with `holds_at_pod_terminal` to determine if a container can be picked up * **Hold and fee enum references** β€” quick-reference tables for all hold names and fee types, with expandable details for each value * **Webhook changeset examples** β€” how to subscribe to `container.updated` and react to hold/fee changes in real time * **Rail and inland destinations** β€” clarification that the same fields apply at inland rail terminals, not just the port of discharge * **FAQ** β€” answers to common integration questions like double-counting fees, sync lag between holds and availability, and case-sensitive hold names Container Holds, Fees, and Release Readiness ### Infer Tracking Number (Beta) Added the **Infer Tracking Number** endpoint to help you predict: * The **VOCC SCAC** to use for tracking * The **number type** (container, bill of lading, booking) * A confidence-driven **decision** (`auto_select`, `needs_confirmation`, `no_prediction`) Infer Tracking Number endpoint details How to use Infer Tracking Number in your workflow Use Infer Tracking Number when you have a valid tracking number but don’t know the correct **VOCC SCAC**. ### Documentation improvements Added an **Updates** section to publish API/DataSync changes. Added cross-links from relevant docs to Infer Tracking Number.