{"openapi":"3.1.0","info":{"title":"Traqo Ocean API","version":"1.0.0","description":"Real-time ocean container, bill-of-lading and vessel tracking. Authenticate with a Bearer API key (Developer mode must be enabled on your account). Full reference, examples and a live sandbox: https://traqocontainer.com/developer","contact":{"name":"Traqo Ocean","url":"https://traqocontainer.com/developer"}},"servers":[{"url":"https://traqocontainer.com/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Tracking","description":"Track containers and bills of lading"},{"name":"Vessels","description":"Vessel position lookup"},{"name":"Voyages","description":"Sailing schedules"},{"name":"Ports","description":"Port congestion analytics"},{"name":"Reference","description":"Supported carriers"}],"paths":{"/container/{number}":{"get":{"tags":["Tracking"],"summary":"Track a container","description":"Full tracking data for a container number. Saves the shipment to your account (consumes a slot if new).","operationId":"trackContainer","security":[{"bearerAuth":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z]{4}[0-9]{7}$"},"example":"MRSU6859427","description":"Container number: 4 letters + 7 digits."},{"name":"sealine","in":"query","required":true,"schema":{"type":"string","minLength":4,"maxLength":4},"example":"MAEU","description":"Required 4-character SCAC of the carrier."}],"responses":{"200":{"description":"Tracking data","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true,"properties":{"reference_number":{"type":"string"},"sealine":{"type":"string","description":"4-char SCAC of the carrier"},"sealine_name":{"type":"string"},"status":{"type":"string"},"eta":{"type":["string","null"],"format":"date-time","description":"Carrier-reported ETA, passed through unmodified. It is INTENDED to be arrival at the port of discharge, but some carrier feeds report an earlier milestone (such as the estimated on-board date) or leave a past date in place on a moving shipment. Always check `eta_reliable` before acting on this value."},"eta_reliable":{"type":"boolean","description":"False when we can demonstrate the carrier ETA is wrong — it has already elapsed while the shipment is still in transit, or it implies a physically impossible transit. True otherwise, including when no ETA was supplied."},"eta_warning":{"type":["string","null"],"description":"Human-readable explanation when `eta_reliable` is false; null otherwise."},"origin":{"type":["string","null"]},"destination":{"type":["string","null"]}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/bl/{number}":{"get":{"tags":["Tracking"],"summary":"Track a bill of lading","description":"Full tracking data for a Bill of Lading number. `sealine` is mandatory — a BL carries no embedded carrier code.","operationId":"trackBillOfLading","security":[{"bearerAuth":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":50},"example":"MEDUFR123456","description":"Bill of Lading number, exactly as the carrier printed it. No format is imposed — digits-only BLs and BLs containing hyphens, slashes or dots are all accepted (URL-encode a / as %2F). Surrounding whitespace is trimmed."},{"name":"sealine","in":"query","required":true,"schema":{"type":"string","minLength":4,"maxLength":4},"example":"MSCU","description":"Required 4-character SCAC of the carrier."}],"responses":{"200":{"description":"Tracking data","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true,"properties":{"reference_number":{"type":"string"},"sealine":{"type":"string","description":"4-char SCAC of the carrier"},"sealine_name":{"type":"string"},"status":{"type":"string"},"eta":{"type":["string","null"],"format":"date-time","description":"Carrier-reported ETA, passed through unmodified. It is INTENDED to be arrival at the port of discharge, but some carrier feeds report an earlier milestone (such as the estimated on-board date) or leave a past date in place on a moving shipment. Always check `eta_reliable` before acting on this value."},"eta_reliable":{"type":"boolean","description":"False when we can demonstrate the carrier ETA is wrong — it has already elapsed while the shipment is still in transit, or it implies a physically impossible transit. True otherwise, including when no ETA was supplied."},"eta_warning":{"type":["string","null"],"description":"Human-readable explanation when `eta_reliable` is false; null otherwise."},"origin":{"type":["string","null"]},"destination":{"type":["string","null"]}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/track":{"post":{"tags":["Tracking"],"summary":"Bulk track shipments","description":"Track up to 50 containers or bills of lading in one request — the batch form of GET /container and GET /bl. Each item needs its 4-char SCAC (`sealine`). New shipments are saved to your account and consume a slot each; ones you already track are re-fetched free. Per-item results: the request returns 200 even when some items fail — branch on each `results[].ok`.","operationId":"bulkTrack","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["shipments"],"properties":{"shipments":{"type":"array","minItems":1,"maxItems":50,"description":"Up to 50 shipments to track in one request.","items":{"type":"object","required":["type","number","sealine"],"properties":{"type":{"type":"string","enum":["container","bl"],"description":"container or bl (bill of lading)."},"number":{"type":"string","description":"Container number (4 letters + 7 digits, ISO 6346 check digit verified) or BL number (3-50 characters as printed by the carrier — no format imposed)."},"sealine":{"type":"string","minLength":4,"maxLength":4,"description":"4-char SCAC of the carrier (see GET /carriers)."}}}}}},"example":{"shipments":[{"type":"container","number":"MRSU6859427","sealine":"MAEU"},{"type":"bl","number":"MEDUFR123456","sealine":"MSCU"}]}}}},"responses":{"200":{"description":"Per-item results (some items may have failed)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"total":{"type":"integer","description":"Number of items processed."},"tracked":{"type":"integer","description":"Items that succeeded."},"failed":{"type":"integer","description":"Items that failed (see each result.error)."},"slots":{"type":"object","properties":{"used":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"}}},"results":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"index":{"type":"integer","description":"Position in the request array."},"number":{"type":["string","null"]},"type":{"type":["string","null"]},"ok":{"type":"boolean"},"slot_consumed":{"type":"boolean","description":"On success — whether a new slot was used (false if already tracked)."},"error":{"type":"string","description":"On failure — one of invalid_request, shipment_limit, not_found, fetch_failed, upstream_error."},"message":{"type":"string"},"data":{"type":"object","additionalProperties":true,"description":"On success — the tracking document (same shape as GET /container)."}}}}},"required":["success","results"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/carriers":{"get":{"tags":["Reference"],"summary":"List supported carriers","description":"Every ocean carrier Traqo can track, with its 4-char SCAC and name. The SCAC is exactly what you pass as the `sealine` parameter on /container, /bl and /track. Local read — never consumes a slot.","operationId":"listCarriers","security":[{"bearerAuth":[]}],"parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string","minLength":2},"example":"maersk","description":"Optional case-insensitive filter by SCAC, name or slug (≥2 chars)."}],"responses":{"200":{"description":"Supported carriers","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"total":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"scac":{"type":"string","description":"4-char SCAC — use as the `sealine` parameter."},"name":{"type":"string"},"slug":{"type":"string"}}}}},"required":["success","data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/shipments":{"get":{"tags":["Tracking"],"summary":"List tracked shipments","description":"Paginated list of the shipments saved to your account. Local read — never consumes a slot.","operationId":"listShipments","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"A page of shipments","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"page":{"type":"integer"},"pageSize":{"type":"integer"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["success","data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/shipments/{id}":{"get":{"tags":["Tracking"],"summary":"Get a shipment","description":"A saved shipment summary (status, ETA, route) from local data — no upstream re-track, never consumes a slot. Includes predictive_eta / demurrage_risk when enabled on your plan.","operationId":"getShipment","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The shipment id (as returned by /shipments)."}],"responses":{"200":{"description":"Shipment summary","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Tracking"],"summary":"Untrack a shipment","description":"Soft-deletes the shipment from your account so it stops counting toward your slot limit. Local — never consumes a slot. 404 if it is not one of your tracked shipments.","operationId":"untrackShipment","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The shipment id to untrack."}],"responses":{"200":{"description":"Untracked; slot freed","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/vessel/track":{"get":{"tags":["Vessels"],"summary":"Track a vessel","description":"A vessel's latest AIS position. Pure lookup — never consumes a slot. Both imo and mmsi are required.","operationId":"trackVessel","security":[{"bearerAuth":[]}],"parameters":[{"name":"imo","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9]{7}$"},"example":"9321483","description":"IMO number: exactly 7 digits."},{"name":"mmsi","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9]{9}$"},"example":"636014784","description":"MMSI number: exactly 9 digits."}],"responses":{"200":{"description":"Vessel position","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/voyage/schedules":{"get":{"tags":["Voyages"],"summary":"Voyage schedules","description":"Point-to-point sailing schedules between two ports. Pure lookup — never consumes a slot.","operationId":"voyageSchedules","security":[{"bearerAuth":[]}],"parameters":[{"name":"origin","in":"query","required":true,"schema":{"type":"string","minLength":5,"maxLength":5},"example":"INMUN","description":"Origin UN/LOCODE (5 chars)."},{"name":"destination","in":"query","required":true,"schema":{"type":"string","minLength":5,"maxLength":5},"example":"AEJEA","description":"Destination UN/LOCODE (5 chars)."},{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date"},"example":"2026-06-01","description":"Reference date, YYYY-MM-DD."},{"name":"week_range","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":8,"default":1},"description":"Number of weeks from the date to include."},{"name":"date_type","in":"query","required":false,"schema":{"type":"string","enum":["departure","arrival"],"default":"departure"}}],"responses":{"200":{"description":"Matching schedules","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/ports/congestion":{"get":{"tags":["Ports"],"summary":"Congestion board","description":"The current congestion reading for every scored port in one call — score / bucket / tier plus a 7-day trend and 30-day call volume. Reads Traqo analytics; never consumes a slot. Requires port-congestion on your plan.","operationId":"congestionBoard","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All scored ports","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/ports":{"get":{"tags":["Ports"],"summary":"Search ports","description":"Directory lookup against the Traqo port table — resolve a UN/LOCODE, port name, or city to canonical metadata. Local read; never consumes a slot.","operationId":"searchPorts","security":[{"bearerAuth":[]}],"parameters":[{"name":"search","in":"query","required":true,"schema":{"type":"string","minLength":2},"example":"rotterdam","description":"A UN/LOCODE, port name, or city — at least 2 characters."}],"responses":{"200":{"description":"Matching ports (max 25, exact-LOCODE first)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/ports/{locode}/congestion":{"get":{"tags":["Ports"],"summary":"Port congestion","description":"A port's latest congestion score and 90-day history. Reads Traqo analytics — never consumes a slot. Requires port-congestion on your plan.","operationId":"portCongestion","security":[{"bearerAuth":[]}],"parameters":[{"name":"locode","in":"path","required":true,"schema":{"type":"string","minLength":5,"maxLength":5},"example":"INNSA","description":"Port UN/LOCODE (5 chars)."}],"responses":{"200":{"description":"Congestion score + history","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"locode":{"type":"string"},"score":{"type":"number"},"bucket":{"type":"string","enum":["fluid","normal","moderate","high","critical"]},"tier":{"type":"string","enum":["A","B","C"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"webhooks":{"shipment.updated":{"post":{"summary":"A tracked shipment's status changed (non-arrival).","operationId":"webhook_shipment_updated","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"event":{"const":"shipment.updated"},"data":{"$ref":"#/components/schemas/ShipmentEventData"}}}]}}}},"responses":{"200":{"description":"Return any 2xx within 10s to acknowledge. Non-2xx / timeout is retried with backoff."}}}},"shipment.arrived":{"post":{"summary":"A tracked shipment became delivered / completed.","operationId":"webhook_shipment_arrived","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"event":{"const":"shipment.arrived"},"data":{"$ref":"#/components/schemas/ShipmentEventData"}}}]}}}},"responses":{"200":{"description":"Return any 2xx within 10s to acknowledge. Non-2xx / timeout is retried with backoff."}}}},"eta.changed":{"post":{"summary":"A tracked shipment's carrier ETA changed.","operationId":"webhook_eta_changed","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"event":{"const":"eta.changed"},"data":{"$ref":"#/components/schemas/ShipmentEventData"}}}]}}}},"responses":{"200":{"description":"Return any 2xx within 10s to acknowledge. Non-2xx / timeout is retried with backoff."}}}},"discovery.recovered":{"post":{"summary":"Carrier auto-discovery recovered a shipment that first failed to track.","operationId":"webhook_discovery_recovered","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"event":{"const":"discovery.recovered"},"data":{"$ref":"#/components/schemas/DiscoveryRecoveredData"}}}]}}}},"responses":{"200":{"description":"Return any 2xx within 10s to acknowledge. Non-2xx / timeout is retried with backoff."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key as a Bearer token: `Authorization: Bearer YOUR_API_KEY`."}},"responses":{"BadRequest":{"description":"Bad request — check required parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Invalid or missing API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"Payment required — shipment limit reached or payment overdue. Branch on `data.error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Developer mode not enabled, or the feature is not on your plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"Upstream tracking API error — retry after a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"statusCode":{"type":"integer","example":401},"statusMessage":{"type":"string","example":"Invalid or missing API key"},"data":{"type":"object","additionalProperties":true,"description":"Present on some errors (e.g. 402 carries error/manageUrl)."}},"required":["statusCode","statusMessage"]},"WebhookEnvelope":{"type":"object","description":"Every webhook delivery POSTs this envelope. Verify the X-Traqo-Signature header against the raw body.","properties":{"event":{"type":"string","example":"shipment.updated"},"created":{"type":"integer","description":"Unix timestamp (seconds).","example":1754170000},"data":{"type":"object","additionalProperties":true}},"required":["event","created","data"]},"ShipmentEventData":{"type":"object","properties":{"shipment_id":{"type":"string"},"reference_number":{"type":["string","null"]},"carrier":{"type":["string","null"]},"status":{"type":["string","null"]},"previous_status":{"type":["string","null"]},"eta":{"type":["string","null"],"format":"date-time"},"previous_eta":{"type":["string","null"],"format":"date-time"}}},"DiscoveryRecoveredData":{"type":"object","properties":{"reference_number":{"type":"string"},"type":{"type":"string","enum":["Container","BL"]},"carrier":{"type":["string","null"]},"carrier_name":{"type":["string","null"]},"shipment_id":{"type":["string","null"]}}}}}}