Skip to main content

Webhook

Shipment Webhook Event Subscription

Shipment Webhook event subscription is a service that delivers updated data in real time to subscribed endpoints when shipment data changes.

When a subscribed event occurs, the JSON payload is delivered to the registered endpoint via the request body.

The detailed structure of the JSON payload is as follows.

Events Object

{
"event_id": "31b1a972-677b-422c-a696-4228e3b5a8ff",
"event_occurred_at": "2025-12-01T04:22:15.805606262",
"event_name": "SHIPMENT.BL.UPDATED",
"payload": {}
}
FieldsTypeDescription
event_idStringUnique identifier that identifies the event
event_occurred_atStringTime when the event occurred yyyy-MM-dd'T'HH:mm:ss.SSSSSS
event_nameStringName of the event that occurred
payloadObjectThe payload value corresponding to the occurred event is delivered.

SHIPMENT.BL.UPDATED PAYLOAD

{
"cargo_track_id": "3d8b1e76-8721-4e27-a98d-2bfb8193d4ee",
"line_cd": "HMM",
"bl_no": "HDMUPUSM12345678",
"cust_order_id": "REFERENCE_NO",
"cust_corp_name": null,
"cust_name": null,
"remark": null,
"is_active": true,
"registered_datetime": "2025-12-01T04:22:06.6305903Z",
"tracking_status": "TRACKING",
"is_container_plus": true,
"trade_type": "EXPRT",
"trans_type": "DIRECT",
"pol": {
"pol_name": "New Busan",
"pol_code": "KRBNP",
"init_etd": "2025-12-06T00:00:00+09:00",
"etd": "2025-12-06T00:00:00+09:00",
"atd": null,
"tx_atd": "2025-12-06T00:00:00+09:00"
},
"pod": {
"pod_name": "Manzanillo",
"pod_code": "MXZLO",
"init_eta": "2025-12-19T18:00:00-06:00",
"eta": "2025-12-19T18:00:00-06:00",
"ata": null,
"tx_ata": null
},
"current_vessel": {
"imo": "9976707",
"mmsi": "563262300",
"vessel_name": "ONE SAPPHIRE",
"voyage": "2547E"
},
"routes": [
{
"order": 1,
"pol_name": "New Busan",
"pol_code": "KRBNP",
"pod_name": "Manzanillo",
"pod_code": "MXZLO",
"imo": "9976707",
"mmsi": "563262300",
"vessel_name": "ONE SAPPHIRE",
"voyage": "2547E",
"init_etd": "2025-12-06T00:00:00+09:00",
"etd": "2025-12-06T00:00:00+09:00",
"atd": null,
"tx_atd": "2025-12-06T00:00:00+09:00",
"init_eta": "2025-12-19T18:00:00-06:00",
"eta": "2025-12-19T18:00:00-06:00",
"ata": null,
"tx_ata": null
}
],
"containers": [
{
"cntr_no": "CAIU7471046",
"cntr_sz": "40",
"cntr_tp": "DC",
"container_events": [
{
"port_code": "KRPUS",
"event_type": "LOADING_ON_VESSEL",
"transportation": "VESSEL",
"is_actual": true,
"event_datetime": "2025-12-05T16:45:00+09:00"
},
{
"port_code": "KRPUS",
"event_type": "VESSEL_DEPARTURE_FROM_PORT",
"transportation": "VESSEL",
"is_actual": true,
"event_datetime": "2025-12-06T00:00:00+09:00"
},
{
"port_code": "MXZLO",
"event_type": "VESSEL_ARRIVAL_AT_PORT",
"transportation": "VESSEL",
"isActual": false,
"event_datetime": "2025-12-19T17:00:00-06:00"
},
{
"port_code": "MXZLO",
"event_type": "VESSEL_BERTHING_ON_PORT",
"transportation": "VESSEL",
"isActual": false,
"event_datetime": "2025-12-19T18:00:00-06:00"
},
{
"port_code": "MXZLO",
"event_type": "DISCHARGING_FROM_VESSEL",
"transportation": "VESSEL",
"isActual": false,
"event_datetime": "2025-12-20T11:02:24-06:00"
}
]
}
]
}

Payload

FieldTypeDescription
cargo_track_idStringCargo Tracking ID
line_cdStringCarrier code
bl_noStringB/L number
cust_order_idStringCustomer order ID (Reference/Order ID)
cust_corp_nameString | nullCustomer company name
cust_nameString | nullCustomer name
remarkString | nullRemark
is_activeBooleanWhether tracking is active
registered_datetimeStringRegistered datetime (ISO-8601, e.g. yyyy-MM-dd'T'HH:mm:ssZ)
tracking_statusStringTracking status (e.g. INIT, PENDING, TRACKING, COMPLETE, etc.)
is_container_plusBooleanWhether Container Plus is enabled
trade_typeStringTrade type (EXPRT/IMPRT)
trans_typeStringTransportation type (e.g. DIRECT, TS, etc.)
polObjectPOL (Port of Loading) object
podObjectPOD (Port of Discharge) object
current_vesselObjectCurrent vessel object
routesArray<Object>Route/leg list
containersArray<Object>Container list

Tracking Status

CodeDescription
INITWaiting
PENDINGRetrying
EXPIREDRetry failed for 7 days
BL_INVALIDInvalid BL input
TRACKINGTracking
COMPLETECompleted
UNPAIDInsufficient credits

POL Information

FieldTypeDescription
pol.pol_nameStringPort of loading name
pol.pol_codeStringPort of loading code
pol.init_etdString | nullInitially collected ETD yyyy-MM-dd'T'HH:mm:ssXXX
pol.etdString | nullETD yyyy-MM-dd'T'HH:mm:ssXXX
pol.atdString | nullATD yyyy-MM-dd'T'HH:mm:ssXXX
pol.tx_atdString | nullATD provided by TRADLINX yyyy-MM-dd'T'HH:mm:ssXXX

POD Information

FieldTypeDescription
pod.pod_nameStringPort of discharge name
pod.pod_codeStringPort of discharge code
pod.init_etaString | nullInitially collected ETA yyyy-MM-dd'T'HH:mm:ssXXX
pod.etaString | nullETA yyyy-MM-dd'T'HH:mm:ssXXX
pod.ataString | nullATA yyyy-MM-dd'T'HH:mm:ssXXX
pod.tx_ataString | nullATA provided by TRADLINX yyyy-MM-dd'T'HH:mm:ssXXX

Current Vessel Information

FieldTypeDescription
current_vessel.imoStringIMO number
current_vessel.mmsiStringMMSI number
current_vessel.vessel_nameStringVessel name
current_vessel.voyageStringVoyage

routes[*]

FieldTypeDescription
routes[].orderNumberLeg order
routes[].pol_nameStringPort of loading name
routes[].pol_codeStringPort of loading code
routes[].pod_nameStringPort of discharge name
routes[].pod_codeStringPort of discharge code
routes[].imoStringIMO number
routes[].mmsiStringMMSI number
routes[].vessel_nameStringVessel name
routes[].voyageStringVoyage
routes[].init_etdStringInitially collected ETD yyyy-MM-dd'T'HH:mm:ssXXX
routes[].etdString | nullETD yyyy-MM-dd'T'HH:mm:ssXXX
routes[].atdString | nullATD yyyy-MM-dd'T'HH:mm:ssXXX
routes[].tx_atdString | nullATD provided by TRADLINX yyyy-MM-dyyyy-MM-dd'T'HH:mm:ssXXX
routes[].init_etaString | nullInitially collected ETA yyyy-MM-dd'T'HH:mm:ssXXX
routes[].etaString | nullETA yyyy-MM-dd'T'HH:mm:ssXXX
routes[].ataString | nullATA yyyy-MM-dd'T'HH:mm:ssXXX
routes[].tx_ataString | nullATA provided by TRADLINX yyyy-MM-dyyyy-MM-dd'T'HH:mm:ssXXX

containers[*]

FieldTypeDescription
containers[].cntr_noStringContainer number
containers[].cntr_szStringSize
containers[].cntr_tpStringType
containers[].seal_noStringSeal number
containers[].container_eventsArrayContainer event list

containers[].containerEvents[*]

FieldTypeDescription
containers[].container_events[].port_codeStringPort code
containers[].container_events[].event_typeStringEvent type
containers[].container_events[].transportationStringTransportation mode
containers[].container_events[].is_actualBooleanWhether actual
containers[].container_events[].event_datetimeStringEvent datetime yyyy-MM-dd'T'HH:mm:ssXXX

Container Event Types

CodeDescription
CONTAINER_PICK_UPContainer pickup
LOADING_ON_VESSELLoading on vessel
VESSEL_DEPARTURE_FROM_PORTVessel departure from port
VESSEL_ARRIVAL_AT_PORTVessel arrival at port
VESSEL_BERTHING_ON_PORTVessel berthing at port
DISCHARGING_FROM_VESSELDischarging from vessel
GATE_INGate in to terminal or container yard
GATE_OUTGate out from terminal or container yard
RAIL_LOADINGRail loading
RAIL_DEPARTURERail departure
RAIL_ARRIVALRail arrival
RAIL_UNLOADINGRail unloading
PICKING_UP_BY_CONSIGNEECargo is being picked up by the consignee to take delivery
DELIVERING_TO_CONSIGNEECargo is being delivered to the consignee
EMPTY_CONTAINER_RETURNEmpty container return

Transportation Mode Types

CodeDescription
VESSELVessel
FEEDERFeeder vessel (small container vessel)
BARGEBarge (non- or low-powered cargo vessel)
RAILRail (train)
TRUCKTruck

Getting Started

To receive webhook events, you must be operating a server that can receive webhook events.

Register and test your endpoint by following the steps below.


1. Create a Webhook Endpoint Function

TRADLINX Webhook is delivered as a JSON payload.

Therefore, you must implement an HTTPS endpoint that can handle webhook requests.

Endpoint Configuration Guide

  • The endpoint host supports HTTPS protocol only.
  • Implement an endpoint that allows the event you want to subscribe to and the HTTP method (GET, POST, etc.) supported by that event.
  • The request body is a JSON payload.
  • After receiving the payload, your endpoint must return an HTTP status of 2xx (200, 201, etc.) to be recorded as successfully received.
    • Other statuses are not recorded as successful, and if failures repeat, the endpoint may be switched to an inactive state.
  • Process the payload as quickly as possible.
    • If the volume of webhook deliveries surges, the endpoint host may be overloaded.
    • If the response waiting time exceeds 10 seconds and repeats 3 or more times, it may be switched to an inactive state.
    • To prevent these issues, asynchronous processing is recommended.

Recommended logic that the endpoint should perform

  • Parse the received JSON payload
  • Extract key fields such as event_id, event_name, event_occurred_at, payload.cargo_track_id, etc.
    • event_id can be used later to re-send failed events.
  • Record receipt success/failure in a monitoring system

2. Register the Endpoint

  • Currently, webhook endpoints are managed directly by TRADLINX.

  • Please send the following information to tech.support@tradlinx.com.

    • The currently supported event is SHIPMENT.BL.UPDATED, and requests are made only with HTTP METHOD: POST.

    Submission Items

ItemDescription
Event name to registerSHIPMENT.BL.UPDATED
Webhook Endpoint URLPublicly accessible HTTPS URL https://<your-website>/<your-webhook-endpoint>
AuthorizationTRADLINX supports HTTP Basic Authentication by default. When registering your Webhook Endpoint, please provide a Username and Password. When sending webhooks, TRADLINX will include the Authorization header in the form Basic {credentials}, where {credentials} is the Base64-encoded value of the username:password string. If you require additional/custom headers beyond Basic Auth, prior coordination is required.


3. Test

Once webhook endpoint registration is completed, a test mock event is automatically generated.

Using the API below, you can view the list of webhook events provided by TRADLINX or manually publish the mock event to the endpoint by re-sending it directly.

Use the mock event re-send feature to test whether your webhook endpoint works properly.


4. Handle Webhook Events (Update Tracking Data)

  • To receive webhooks properly, you must register the shipments to be tracked via the API or SaaS (OceanVisibility).
  • Webhooks are sent for shipments among registered tracking targets when a progress status change or shipment status change occurs.
  • When receiving a webhook event, process the data by referring to the guide below.

Guide

  • Store the cargo_track_id returned when registering a shipment.
  • The identifier of the shipment data contained in the event payload that is updated when an event occurs is the cargo_track_id returned at registration.
  • Save or update data based on cargo_track_id.
    • If cargo_track_id does not exist in storage, save it as a new shipment record.
    • If cargo_track_id exists in storage, find newer data based on event_occurred_at and update it.

Retrieve Event List

  • Various issues can occur in the process of delivering events to the webhook endpoint (network environment, DNS resolution issues, SSL issues, etc.).
  • TRADLINX may also fail to deliver events properly due to other causes.
  • The retention period for event data is limited to one month, after which the data will be deleted.

Retrieve Occurred Events

  • Events can be checked via the Event List Retrieval API.
  • In the list, you can check each event status (SUCCESS / FAILURE / DELIVERED / DNS_RESOLUTION_FAILURE).
  • Retrieves the webhook delivery history (including success/failure) that occurred for the client account.
  • The request requires authentication headers (tx-clientid, tx-apikey).

Request

GET /partners/track/webhook/events

Authentication Headers

HeaderDescription
tx-clientidClient ID issued for API integration
tx-apikeyAPI key for client authentication

Query Parameters

FieldTypeDescription
*statusStringEvent status to retrieve (SUCCESS_RESPONSE, FAILURE_RESPONSE, DELIVERED, FAILURE_UNKNOWN_HOST, FAILURE_REQUEST_TIMEOUT, FAILURE_CONNECTION_REFUSED)
*pagenumberPage number (min: 1)
*sizenumberPage size (range: 1~1000)

curl -X GET "https://api.tradlinx.com/partners/track/webhook/events?page=[Page]&size=[Size]&status=[Status]" \
-H "tx-clientid: [Client ID]" \
-H "tx-apikey: [API Key]"

Response

{
"content": [
{
"id": "8f6c1c4b-0ae4-4f31-9df7-2a13d5e4bc11",
"event_name": "SHIPMENT.BL.UPDATED",
"status": "SUCCESS_RESPONSE",
"payload": "{\"sample\": \"payload\"}",
"payload_type": "REAL",
"payload_version": "v1",
"is_resendable": true,
"occurred_datetime": "2025-12-10T14:22:11",
"created_datetime": "2025-12-10T14:22:12"
},
{
"id": "4c2a7512-9b5c-4bd1-bd0a-afb22d8c1120",
"event_name": "SHIPMENT.BL.UPDATED",
"status": "SUCCESS_RESPONSE",
"payload": "{\"sample\": \"payload\"}",
"payload_type": "REAL",
"payload_version": "v1",
"is_resendable": false,
"occurred_datetime": "2025-12-10T14:20:02",
"created_datetime": "2025-12-10T14:20:03"
}
],
"pagination": {
"current_page": 1,
"has_next": false,
"total_page": 10,
"total_size": 10
}
}

Response

FieldTypeDescriptionRemark
api_versionstringAPI versionv3
contentEventEvents
transaction_timestringTime when the response was providedyyyy-MM-dd'T'HH:mm:ss.SSSSSS
sizenumberSize of content
paginationPaginationPagination info

Pagination

FieldTypeDescription
total_sizenumberTotal data size
total_pagenumberMaximum page number
current_pagenumberCurrent page number
has_nextbooleanWhether there is a next page

Event

FieldsTypeDescription
idstringUnique Webhook event ID
event_namestringWebhook event name
statusstringWebhook request result status
payloadstringRaw JSON payload sent in the actual webhook request
payload_typestringIndicates whether the payload is test (Mock) data
payload_versionstringPayload version
is_resendablebooleanWhether the event can be resent
occurred_datetimestringTime when the event occurred yyyy-MM-dd'T'HH:mm:ss.SSSSSS
created_datetimestringTime when it was stored as a log yyyy-MM-dd'T'HH:mm:ss.SSSSSS

Status Code Details

CodeDescription
SUCCESS_RESPONSEThe target server returned a successful (2xx) response to the webhook request
FAILURE_RESPONSEThe target server did not return a successful (2xx) response to the webhook request
DELIVEREDThe event occurred at Tradlinx; status before sending the request to the endpoint
FAILURE_UNKNOWN_HOSTThe endpoint host could not be resolved via DNS
FAILURE_REQUEST_TIMEOUTThe request to the endpoint timed out
FAILURE_CONNECTION_REFUSEDThe endpoint host refused the connection

Payload Type Details

CodeDescription
MOCKTest payload
REALPayload generated by a real event

Retrieve the Event Detail

By looking up the details of a specific event, you can check the following information:

  • HTTP status code of the delivery attempt
  • Response body
  • Response headers
  • Attempt time

Using this information, you can quickly determine why the webhook endpoint failed to receive the event.

Retrieves all request attempt logs for a specific webhook event.

If an event is retried multiple times, all attempts are returned as an array.

Request

GET /partners/track/webhook/events/{event_id}/log

Path Variable

VariableTypeDescription
event_idstringWebhook Event ID to retrieve

Authentication Headers

HeaderDescription
tx-clientidClient ID issued for API integration
tx-apikeyAPI key for client authentication
curl -X GET "https://api.tradlinx.com/partners/track/webhook/events/[Event ID]/log" \
-H "tx-clientid: [Client ID]" \
-H "tx-apikey: [API Key]"

Response

{
"content": [
{
"id": 101,
"event_id": "8f6c1c4b-0ae4-4f31-9df7-2a13d5e4bc11",
"request_cause": "SUCCESS",
"request_method": "POST",
"request_url": "https://api.example.com/webhook",
"request_status": "SUCCESS",
"request_datetime": "2025-12-10T14:10:20.123456",
"response_http_status": 200,
"response_body": "{\"result\":\"ok\"}",
"response_header": "{\"Content-Type\":\"application/json\"}",
"response_datetime": "2025-12-10T14:10:20.543210",
"attempts": 1
},
{
"id": 102,
"event_id": "8f6c1c4b-0ae4-4f31-9df7-2a13d5e4bc11",
"request_cause": "SUCCESS",
"request_method": "POST",
"request_url": "https://api.example.com/webhook",
"request_status": "FAILED",
"request_datetime": "2025-12-10T14:12:05.333222",
"response_http_status": 504,
"response_body": "",
"response_header": "{\"Content-Type\":\"application/json\"}",
"response_datetime": "2025-12-10T14:12:10.888999",
"attempts": 2
}
],
"pagination": {
"current_page": 1,
"has_next": false,
"total_page": 10,
"total_size": 10
}
}

Response Body

FieldTypeDescriptionRemark
api_versionstringAPI versionv3
contentEventLogEvent logs
transaction_timestringTime when the response was providedyyyy-MM-dd'T'HH:mm:ss.SSSSSS
sizenumberSize of content
paginationPaginationPagination info

Pagination

FieldTypeDescription
total_sizenumberTotal data size
total_pagenumberMaximum page number
current_pagenumberCurrent page number
has_nextbooleanWhether there is a next page

Event Log

FieldTypeDescription
idnumberUnique attempt ID
event_idstringParent Webhook Event ID
request_causestringReason/cause for the request
request_methodstringHTTP method (POST, etc.)
request_urlstringRequest URL
request_statusstringRequest status (SUCCESS / FAILED, etc.)
request_datetimestringTime when the request was made yyyy-MM-dd'T'HH:mm:ss.SSSSSS
response_http_statusnumberHTTP status code returned by the target server
response_bodystringResponse body returned by the target server (raw string)
response_headerstringResponse headers returned by the target server (raw JSON string)
response_datetimestringTime when the response was completed yyyy-MM-dd'T'HH:mm:ss.SSSSSS
attemptsnumberTotal number of attempts for the event

requestCause

ValueDescription
ON_EVENTNormal case: the webhook request was triggered by an event occurrence
RETRY_ON_FAILURE_RESPONSERetry webhook request triggered due to a non-2xx response
RETRY_ON_FAILURE_REQUEST_TIMEOUTRetry webhook request triggered due to a request timeout
ON_APIThe event was triggered via API

requestStatus

ValueDescription
PENDINGRequest has been sent to the endpoint and is waiting for a response
SUCCESSRequest has been sent to the endpoint and a response was received
FAILURE_UNKNOWN_HOSTRequest was made to a host that cannot be resolved via DNS
FAILURE_REQUEST_TIMEOUTRequest to the endpoint timed out
FAILURE_CONNECTION_REFUSEDThe endpoint host refused the connection
UNKNOWNUnknown failure

Webhook Retry (Automatic + Manual)

If the webhook endpoint fails to receive an event, TRADLINX performs up to 3 automatic retries using an exponential backoff strategy after an initial 2-second delay.

If the event is still not received despite automatic retries, the user can check failed events via the Event List Retrieval API provided in the API documentation.

If you want to receive a specific event again, call the Webhook Event Resend API using the event_id obtained from the list to immediately receive that event again.

Webhook Event Resend

  • Force re-send (retry) a specific webhook event.
  • Retries are performed regardless of the event’s existing status (SUCCESS/FAILURE, etc.).
  • The retention period for event data is limited to one month. After this period, the data will be deleted, and deleted events cannot be resent

Request

POST /partners/track/webhook/events/{eventId}

Path Variable

VariableTypeDescription
eventIdstringWebhook Event ID to resend

Authentication Headers

HeaderDescription
tx-clientidClient ID issued for API integration
tx-apikeyAPI key for client authentication

Response

200 on success

4xx Error

{
"error_detail": "NOT_FOUND_ENDPOINT",
"transaction_time": "2025-03-20T05:42:27.135265"
}

Duplicate Event Handling

Depending on network conditions or retry policies,

the webhook endpoint may receive the same event multiple times.

Since TRADLINX re-sends with the same event_id during retries,

the receiving (client) endpoint must implement logic to prevent duplicate event processing.

Deduplication Rules

  • When receiving an event, record whether the event has already been processed based on event_id.
  • If the same event_id is received again, it is a retried event, so check occurred_datetime to determine whether it is the latest event.
  • If processing has already been completed for the same event_id, it must be ignored without re-running business logic.

Recommended Approach

  • Record a “processed” status in a database, Redis, or other storage based on event_id.
  • If a re-received event exists, ignore it immediately or only log it.