TimeToCargo

Terminal49

Migrate from Terminal49 to TimeToCargo API v2: authentication, requests and response handling

This guide covers migration from Terminal49 API v2 to TimeToCargo API v2. Terminal49 uses JSON:API with separate tracking request, shipment and container records. The tables below show how to initiate tracking and preserve relationships between those records.

See the migration workflow for importing references and setting up notifications. Full TimeToCargo schemas are in the API reference.

Authentication

Terminal49 uses the Authorization: Token … header. The Terminal49 base URL is https://api.terminal49.com/v2. For requests with a body, use Content-Type: application/json. Remove the JSON:API data.attributes wrapper and use the new request schema.

To switch to TimeToCargo:

  1. Create a key in your TimeToCargo account.
  2. Change the base URL to https://tracking.timetocargo.com/v2. For example, the full tracking endpoint is https://tracking.timetocargo.com/v2/tracking.
  3. Send the new key in the api_key query parameter of every request, including batch tasks and webhook management. Keys and tokens from the former provider cannot be reused.

See authentication for key usage and request limits.

Tracking records and identifiers

Terminal49TimeToCargoRequired change
tracking_requestbatch task (partial)Use the task only to retrieve initiation results. Once it completes, save the permanent tracking ID and export tracking_request history separately.
shipmentshipment + tracking dataSave a new ID for each tracked reference. Containers for a bill of lading or booking are nested within that record's result.
containercontainers[]Find a container by containers[].number. There is no separate permanent container ID or container management API here.
transport_eventcontainers[].events[]Read events from the selected container's array. Update code handling and actual/planned date handling using the tables below.

Operation mapping

Terminal49TimeToCargoRequired change
POST /tracking_requestsPOST /v2/tracking/batch → GET /v2/tracking/batchSubmit references in a batch, retrieve the task results, and save the permanent tracking IDs.
GET /tracking_requests/{id}GET /v2/tracking/batch?task_id=… (partial)Poll the task until PROCESSED, then use IDs from data.results[].data.tracking_metadata.id. Tasks are retained for a limited time.
GET /tracking_requestsNo direct equivalentKeep submitted tasks and their results in your import log. There is no operation to list every task.
GET /shipments, GET /containersGET /v2/shipmentsFetch tracking-record pages. Each record's containers are in tracked_item.data.data.containers[].
GET /shipments/{id}, GET /containers/{id}GET /v2/shipmentsFind the record by its saved new ID in the list pages. For an individual container, select it by number within the record.
GET /containers/{id}/transport_eventsGET /v2/shipments → containers[].events[]Read the selected container's events from the stored record. There is no separate paginated event endpoint.
PATCH /tracking_requests/{id}PATCH /v2/shipments/{id} (partial)Move ref_number into note if it fits within 40 characters. This operation cannot change the carrier reference or SCAC.
GET /shipping_linesGET /v2/companiesFind the carrier by SCAC and check support for your reference type in cn, bl and bk.
PATCH /shipments/{id}/stop_tracking, PATCH /shipments/{id}/resume_trackingDELETE /v2/shipments / new initiationTo stop tracking, pass the new IDs in shipmentIds. Reactivate with a tracking request according to the lifecycle guide.
/webhooks, /webhook_notifications/v2/webhooks, /v2/webhook-notificationsRecreate webhooks and update signature verification and notification parsing. Delivery logs are available through /v2/webhook-notifications.

Request parameters

Terminal49TimeToCargoRequired change
data.attributes.request_numbertracked_items[].track_number.valueCopy request_number into tracked_items[].track_number.value. Remove the JSON:API data.attributes wrapper.
data.attributes.request_typetracked_items[].track_number.typeKeep container, replace bill_of_lading with bl, and replace booking_number with bk.
data.attributes.scactracked_items[].companyVerify the SCAC through GET /v2/companies and pass it in tracked_items[].company.
auto_detect_vocc_scaccompany=AUTO (partial)For automatic carrier detection, use company: "AUTO" only with type container. Supply a SCAC for a bill of lading or booking.
POST: ref_numbers[] / initial_custom_fields, PATCH: ref_numbernote + your own storeAfter obtaining the ID, save one label of up to 40 characters as note. Keep reference arrays and custom fields in your database.
include / filter / pagepage / limit / status / need_routeUse page, limit and status for lists, and need_route=true for routes. Remove include and update relationship handling because there is no included array.

Response fields

Select a record from data.data[] in the GET /v2/shipments response. Paths starting with tracked_item are relative to that record. Containers are in tracked_item.data.data.containers[], with events in each container's events[]. In GET /v2/tracking, shipment data is directly under data.

Terminal49TimeToCargoResponse handling
data.id on tracking_requestdata.task_id (partial)Do not use task_id as a permanent ID. Retrieve the task result and save data.results[].data.tracking_metadata.id.
attributes.status: pending / created / faileddata.status + results[].success / statusCheck the task's data.status, then each result's success and status. PROCESSED means processing finished, not that every reference succeeded.
relationships.tracked_object.dataresults[].data.tracking_metadata.idMap the source tracked_object to the new permanent ID. The new response has no JSON:API relationships object.
container.attributes.numbertracked_item.data.data.containers[].numberRead the number from containers[].number. When several containers are returned, select the required entry by number.
transport_event.attributes.eventcontainers[].events[].status_code / actualHandle status_code and actual separately. For example, origin-port loading is CLL and transshipment loading is CLT.
transport_event.attributes.timestamp / timezone / voyage_numbercontainers[].events[].date / voyageRead the event date from date and voyage from voyage. Account for timezone when comparing with the old timestamp. Do not use record creation time as the event date.
pickup_lfd / holds_at_pod_terminal / fees_at_pod_terminalNo direct equivalentKeep the last free pickup day, release holds and fees separately. They cannot be derived from the overall shipment_status.

Response examples

Each pair labels the former-provider and TimeToCargo responses. Expand the longer JSON examples when you need them; the mapping tables remain visible. These are shortened examples with illustrative data. The path above each JSON block identifies the part shown. Paths in the following table start from that part.

Tracking request and background task

Terminal49 — POST /tracking_requests

Shortened response.

{
    "data": {
        "id": "33333333-3333-4333-8333-333333333333",
        "type": "tracking_request",
        "attributes": {
            "request_number": "MSCU1234567",
            "request_type": "container",
            "scac": "MSCU",
            "ref_numbers": ["Order 123"],
            "status": "pending"
        },
        "relationships": {
            "tracked_object": {
                "data": null
            }
        }
    }
}

TimeToCargo — POST /v2/tracking/batch

Shortened response.

{
    "success": true,
    "status": "OK",
    "data": {
        "task_id": "22222222-2222-4222-8222-222222222222"
    }
}

How to map

Terminal49TimeToCargoRequired change
data.id = "33333333-3333-4333-8333-333333333333"data.task_id = "22222222-2222-4222-8222-222222222222"The source ID is persistent, while task_id is temporary. Wait for the task result to obtain the permanent tracking ID.
data.attributes.request_type = "container"No direct equivalentPass the type in tracked_items[].track_number.type when submitting. The short task-creation response does not repeat it.
data.type = "tracking_request"No direct equivalentRemove JSON:API data.type handling. The reference type is separate and accepts container, bl or bk.
data.attributes.ref_numbers = ["Order 123"]No direct equivalentSave the label with a separate PATCH /v2/shipments/{id} after obtaining the permanent ID. The task-creation response does not yet contain note.

The creation response contains only the task ID. After PROCESSED, retrieve the permanent ID from data.results[].data.tracking_metadata.id. Use it to locate the stored record and update its label.

Container, parent shipment and equipment

How to map

Terminal49TimeToCargoRequired change
attributes.number = "MSCU1234567"tracked_item.data.data.containers[0].number = "MSCU1234567"The container number remains unchanged. Use it to select an entry in containers[].
id = "33333333-3333-4333-8333-333333333333"id = "11111111-1111-4111-8111-111111111111"Map the Terminal49 container ID to the new tracking ID and container number. One document result may include several containers.
relationships.shipment.data.id = "66666666-6666-4666-8666-666666666666"No direct equivalentRetain the source parent shipment ID in your relationship table. The new response has no separate field for that ID.
attributes.current_status = "on_ship"tracked_item.data.data.shipment_status = "IN_TRANSIT"This example has one container in transit, so the status is IN_TRANSIT. For a multi-container result, do not assign one container's status to all others.
attributes.ref_numbers = ["Order 123"]note = "Order 123"Move Order 123 into note. Retain other ref_numbers entries separately.
attributes.equipment_height = "high_cube"tracked_item.data.data.containers[0].type = "40' High Cube Dry"Size, height and type are combined in the containers[].type string. There is no separate equipment_height.

Transport events: codes, dates and actual status

How to map

Terminal49TimeToCargoRequired change
[0].attributes.event = "container.transport.vessel_loaded"containers[0].events[1].status_code = "CLL"Origin-port loading in this example corresponds to CLL. Use CLT for a transshipment loading event.
[1].attributes.event = "container.transport.estimated.vessel_arrived"containers[0].events[0].actual = falseCheck actual=false for estimated arrival. The vessel-arrival code remains VAD.
[0].attributes.timestamp = "2026-10-01T04:00:00Z"containers[0].events[1].date = "2026-10-01T12:00:00"In this example, 04:00 UTC is 12:00 in Singapore. Use the source timezone when converting dates rather than removing Z.
[0].attributes.location_locode = "SGSIN"locations[0].name = "Singapore"Resolve event.location through locations. Use UN/LOCODE SGSIN to verify the source location.
[0].attributes.voyage_number = "126E"containers[0].events[1].voyage = "126E"Read the voyage from event.voyage instead of voyage_number. The value 126E remains unchanged.
[0].id = "77777777-7777-4777-8777-777777777777"No direct equivalentNew response events do not have this ID. Keep the source ID with archived data if your system references it.

Data to retain separately

Separately retain terminal details, last free pickup dates, release holds, fees and custom fields. For each container tracked through a bill of lading or booking, keep the Terminal49 container ID, new tracking ID and container number. This preserves links to former records.

Last updated on