TimeToCargo

ShipsGo

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

This guide covers migration from ShipsGo Ocean API v2 to TimeToCargo API v2. It covers tracking creation, stored data retrieval and route retrieval separately. Legacy ContainerService v1.2 uses different parameters.

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

Authentication

ShipsGo uses the X-Shipsgo-User-Token header. The ShipsGo Ocean v2 base URL is https://api.shipsgo.com/v2.

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

ShipsGoTimeToCargoRequired change
shipment.idshipment.idMap the numeric ShipsGo ID to the new tracking ID. Use the new ID to manage the record.
shipment.containers[]tracked_item.data.data.containers[]In the selected list record, read containers from tracked_item.data.data.containers[]. A bill of lading may contain several.
shipment.reference / tagsnote + your own storeMove one label of up to 40 characters into note. Store remaining tags and metadata in your system.

Operation mapping

ShipsGoTimeToCargoRequired change
POST /ocean/shipmentsPOST /v2/tracking/batch → GET /v2/tracking/batchSubmit references through POST /v2/tracking/batch, retrieve results through GET /v2/tracking/batch, and save data.results[].data.tracking_metadata.id.
GET /ocean/shipmentsGET /v2/shipmentsRetrieve records with page and limit. The status filter selects active or archived subscriptions.
GET /ocean/shipments/{shipment_id}GET /v2/shipmentsFetch list pages and find the record by its saved new ID. There is no individual GET by ID.
PATCH /ocean/shipments/{shipment_id}PATCH /v2/shipments/{id}Send {"note":"your label"} in the body. The limit is 40 characters. This operation does not update other record fields.
DELETE /ocean/shipments/{shipment_id}DELETE /v2/shipmentsPass new IDs in the shipmentIds array. Follow the archiving and deletion rules in the lifecycle guide.
GET /ocean/shipments/{shipment_id}/geojsonGET /v2/shipments?need_route=trueRead route_info from the stored record. If your map needs GeoJSON, convert the point arrays and reverse coordinate order.
GET /ocean/carriersGET /v2/companiesFind the carrier SCAC and check container, bill of lading or booking support in cn, bl and bk.
POST /…/{shipment_id}/tags, DELETE /…/{shipment_id}/tags/{tag_id}PATCH /v2/shipments/{id} (partial)Use note for one label only. Maintain tag collections, individual tag updates and tag-based searches in your own system.
POST/DELETE /…/followersNo direct equivalentMove recipient addresses to your own email system. Webhooks send HTTP notifications, not email subscriptions.

Request parameters

ShipsGoTimeToCargoRequired change
container_numbertracked_items[].track_number.valueIn the batch body, pass the number in tracked_items[].track_number.value and set track_number.type to container.
booking_numbertrack_number.value + typeDetermine whether the field holds a booking or a bill of lading. Put the reference in track_number.value and set type to bk or bl respectively.
carriertracked_items[].companyReplace the ShipsGo carrier code with a SCAC from GET /v2/companies. Map codes such as SG_… before sending company.
reference / tagsnote after creationObtain the permanent tracking ID first, then save the label through PATCH /v2/shipments/{id}. The batch request has no note field.
filters / order_by / skip / takestatus / page / limitReplace skip and take with page and limit. Apply additional filters and sorting in your application after fetching the required pages.

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.

ShipsGoTimeToCargoResponse handling
shipment.iddata.data[].idRead the permanent ID from data.data[].id and map it to the source shipment.id. Do not use the temporary task_id for this mapping.
shipment.carrier.scactracked_item.data.data.summary.company.scacs[]Read codes from summary.company.scacs. It is an array, so check whether it contains the required SCAC.
shipment.statustracked_item.data.data.shipment_statusUse IN_TRANSIT instead of SAILING for an ongoing journey. Handle arrival, discharge and delivery as separate stages.
shipment.containers[].movements[]tracked_item.data.data.containers[].events[]Process containers[].events[]. Read the timestamp from date, the actual flag from actual, and the code from status_code.
shipment.routetracked_item.data.data.summary / route_infoRead ports from summary.pol and summary.pod. With need_route=true, read geometry from route_info.route[].path.

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.

Record, label and shipment state

How to map

ShipsGoTimeToCargoRequired change
id = 1001id = "11111111-1111-4111-8111-111111111111"Save a ShipsGo-to-new-ID mapping. Do not pass 1001 to operations that manage the new tracking record.
reference = "Order 123"note = "Order 123"Save Order 123 as note in a separate request after tracking is created. The maximum length is 40 characters.
container_number = "MSCU1234567"tracked_item.track_number = "MSCU1234567"The number remains unchanged. In the list record, it is in tracked_item.track_number and its type in tracked_item.track_number_type.
status = "SAILING"tracked_item.data.data.shipment_status = "IN_TRANSIT"For the stage shown, use shipment_status: "IN_TRANSIT" instead of SAILING.
containers[0].type = "High Cube Dry"tracked_item.data.data.containers[0].type = "40' High Cube Dry"The new response combines container size and type in containers[].type. Update how those details are displayed.
tagsNo direct equivalentIf note already holds the order reference, keep tags separately. One note cannot represent multiple independent tags.

Container movements, estimates and locations

How to map

ShipsGoTimeToCargoRequired change
number = "MSCU1234567"containers[0].number = "MSCU1234567"Find the container by containers[].number, then process its events.
movements[0].event = "LOAD"containers[0].events[1].status_code = "CLL"Origin-port loading in this example is CLL. For transshipment loading, check CLT.
movements[1].status = "EST"containers[0].events[0].actual = falseReplace ACT with actual=true and EST with actual=false. Do not treat an estimate as a completed event.
movements[1].timestamp = "2026-10-12T08:00:00+02:00"containers[0].events[0].date = "2026-10-12T08:00:00"Parse the +02:00 offset when present. Determine whether the event is actual from actual, not the timestamp format.
movements[0].locationlocations[0]Instead of a nested location object, look up the entry in locations using event.location.
movements[0].vessel.name = "EXAMPLE VESSEL"containers[0].events[1].vessel = "EXAMPLE VESSEL"Read the vessel name from the event.vessel string. Do not expect a nested object with a name and IMO.

Dates illustrate field formats. Preserve source offset and timezone meaning: deleting Z or +08:00 is not a timezone conversion.

GeoJSON and route coordinates

How to map

ShipsGoTimeToCargoRequired change
geometry.coordinatesroute_info.route[0].pathWhen converting GeoJSON, reverse each point from [longitude, latitude] to [latitude, longitude].
properties.current.coordinates = [103.75,1.25]route_info.current_position = [1.25,103.75]Read the current point separately from route_info.current_position. It also uses [latitude, longitude] order.
geometry.type = "LineString"route_info.route[0].type = "sea"Use sea as the transport mode. LineString describes GeoJSON geometry and is not a replacement for sea.
properties.status = "CURRENT"No direct equivalentDo not convert CURRENT into a shipment or subscription status. It describes a ShipsGo route segment and has no dedicated field here.

Data to retain separately

Use GET /v2/shipments?need_route=true to display a stored route. GET /v2/tracking?need_route=true and POST /v2/tracking/batch?need_route=true initiate tracking and may consume credits. If your map uses GeoJSON, convert points from [latitude, longitude] to [longitude, latitude].

Last updated on