Skip to content
Navo24 Navo24
GETAPI keyCounts as a call

Upcoming sailings

GETapi.schedulesmcp.com/public/schedules

Published sailings between two ports, soonest departure first. One entry per carrier offer, so two lines selling the same ship appear as two sailings, each with its own deadlines. Routing comes with the schedule; the field table says what each part means. Every schedule time (departure, arrival, cut-offs, leg times, the window) is the local time of its own port, written without a timezone offset, the way the line publishes it; the two stamps that say when we read or saw something (retrieved_at, last_changed_at, as_of, checked_at) are UTC instants with an offset. It never answers 404: a lane with nothing in the window is a 200 with an empty sailings list. Paged: follow the next link until it is null. By default one routing per departure; routings=all adds the other routings the line publishes. This endpoint needs an API key: send it as Authorization: Bearer. It keeps its /public path, so an existing integration adds the header and changes nothing else.

Counted: 1 call for each answer that carries data. Free: a search that found nothing (200 with an empty sailings list), the following pages of a search fetched through its next link, and any refusal or error. See how calls are counted.

Query parameters

originstringrequired

Origin port UN/LOCODE, e.g. CNSHA

destinationstringrequired

Destination port UN/LOCODE, e.g. NLRTM

fromstring

First departure date to consider, YYYY-MM-DD, matched against each sailing's port-local departure date; today or later, default today.

weeks4 | 8 | 12

Window length in weeks from from: 4, 8 or 12, default 4.

carrierstring

One or more four-character SCAC codes, comma-separated or repeated; omitted means every carrier.

transshipment"true" | "false"

true for sailings with transshipment, false for direct sailings only, omitted for both; any other value is refused.

changed_sincestring

Only sailings new to us, or whose published departure or arrival moved, since this moment; pass back your last as_of.

routings"all"

all returns every routing the line published for each departure, not just the main one.

limitinteger

Sailings per page, 1 to 500, default 100; a value outside the range is refused, not clamped.

cursorstring

An opaque continuation token that next already carries; omit it on the first page and never build or edit it.

Response schema

71 fields

Nested exactly as the JSON is. Open a branch to read its fields; hover a name for the full dot-path.

okboolean

True on every answer that carries data; an error answers false with error instead.

dataobject

The lane, the window used, the per-line summary and this page of sailings.

originstring

The origin UN/LOCODE this answer was built for, which can be the canonical code rather than the one you sent.

origin_namestring | null

The origin port's name, or its UN/LOCODE where we hold no name.

destinationstring

The destination UN/LOCODE this answer was built for, canonical in the same way as origin.

destination_namestring | null

The destination port's name, or its UN/LOCODE where we hold no name.

fromstring

Start of the window, 00:00 of the first departure date considered, port-local with no offset like published_departure.

tostring

End of the window, exclusive, in the same form as from: from plus weeks times seven days.

weeksinteger

The window length in weeks this answer used.

countinteger

How many sailings are on this page, not in the whole window.

carriersarray | null

One entry per line across the whole answer, most sailings first, on the first page only (null on later pages).

carriers[]object
carrier_codestring

The line's SCAC, the same code its sailings carry in carrier_code.

carrier_namestring | null

The line's name, as on its sailings.

countinteger

How many of this line's sailings the whole answer holds across every page, counted exactly as without routings=all.

latest_departurestring | null

This line's last departure in your window, port-local, or null when it has none there.

status"ok" | "no_service" | "timeout" | "failed" | "not_attempted" | "not_supported"

How this line's answer stands for the lane: ok, no_service, timeout, failed, not_attempted or not_supported.

checked_atstring | null

When the line last confirmed this lane (its newest sailing here, or when we asked it), in UTC, or null when we hold no such date.

error"timeout" | "failed" | "paused"

Kept for existing clients, read status instead; paused means two timeouts in a row, so we wait six hours before asking again.

completeboolean | null

True when the live search ran and every listed line is ok, no_service or not_supported, false when a missing sailing may be a gap, null when carriers is null.

transshipmentboolean | null

The transshipment filter as we read it, or null for both kinds.

changed_sincestring | null

The changed_since you sent, as we read it, or null when the whole window was served.

latest_departure_heldstring | null

The last departure anyone has filed on this lane, whatever your window and filters, port-local, or null when none.

as_ofstring

Pass this back as changed_since on your next poll; it is taken before the read, so a delta can repeat a sailing but never skips one.

via_port_namesRecord<string, string>

Port names for every hub code in transship_via on this page.

limitinteger

The page size this answer used: the limit you sent, or 100.

nextstring | null

The next page's request, cursor included: follow it while present and stop only when it is null, never on a short or empty page.

sailingsarray

This page's sailings, soonest departure first, in a stable order so paging neither drops nor repeats one.

sailings[]object
sailing_idstring

The key to store this sailing under; it stays the same when the line moves the dates.

carrier_codestring

The line's SCAC; with a carrier filter, the code you asked for.

carrier_namestring | null

The line's trading name, or null where we hold none; program against carrier_code.

service_namestring | null

The line's own name for the service loop, as published, or null; not comparable across carriers.

vessel_namestring | null

The ship's name, TBN when the line has not named one yet, or null when it gave no ship.

voyage_numberstring | null

The line's voyage number, or null when it has not assigned one.

vessel_imostring | null

The ship's IMO number, or null when we cannot say for certain which ship this is.

vesselobject | null

Particulars of the ship in vessel_imo, or null when we hold none for it.

teuinteger | null

Nominal capacity in TEU; read it with teu_estimated.

teu_estimatedboolean

True when teu is derived from deadweight rather than published for the ship.

flagstring | null

Flag state as a country name, as the vessel register spells it.

year_builtinteger | null

Year the ship was built, from the vessel register.

length_mnumber | null

Ship's length in metres, from the vessel register.

published_departurestring

Departure as the line publishes it, in the origin port's local time, with no offset; do not convert it.

published_arrivalstring | null

Arrival as the line publishes it, in the destination port's local time, with no offset, or null when not published.

departure_precision"minute" | "day" | null

minute when the line published a departure time, day when only a date (the 00:00 is ours), null when unknown.

arrival_precision"minute" | "day" | null

The same as departure_precision, for published_arrival.

cy_cutoffstring | null

Container yard cut-off, port-local with no offset; cutoffs holds every deadline and cutoff_status explains a null.

doc_cutoffstring | null

Documentation cut-off, port-local with no offset; cutoffs holds every deadline and cutoff_status explains a null.

vgm_cutoffstring | null

VGM (verified gross mass) cut-off, port-local with no offset; cutoffs holds every deadline and cutoff_status explains a null.

cutoffsarray | null

Every deadline the line published for this sailing, or null when we hold none (see cutoff_status).

cutoffs[]object
typestring

Normalised deadline code (DCSA where one exists, X- prefixed otherwise); filter and compare on this.

atstring

The deadline in the local time of its port, with no offset.

labelstring | null

The line's own wording for the deadline, to show a person, or null when we hold none.

cutoff_status"published" | "not_published" | "not_held"

Why cut-offs are present or null: published, not_published (the line publishes none), or not_held (we hold none from this line; ask it directly).

last_changed_atstring | null

When we last saw the line move the published departure or arrival, in UTC, or null if never; changed_since filters on this.

is_alternativeboolean

With routings=all only: true for an extra routing of the departure, false for its main one.

retrieved_atstring | null

When the line last confirmed this sailing to us, in UTC; never older than 14 days.

transit_daysinteger | null

The line's own transit time in days, or null when not published.

is_transshipmentboolean | null

True when the box changes ship, false when it does not, null when we cannot tell.

transship_viastring[] | null

Hub UN/LOCODEs on a transshipment, null otherwise.

route_legsarray | null

The routing as the line filed it, one entry per leg in order, or null when we hold none (not the same as direct).

route_legs[]object
leginteger | null

Position of the leg in the routing, from 1.

fromstring | null

The leg's departure port: a UN/LOCODE, or the line's own code where we hold no translation.

from_namestring | null

The departure port's name, or null where we hold none.

tostring | null

The leg's arrival port: a UN/LOCODE, or the line's own code where we hold no translation.

to_namestring | null

The arrival port's name, or null where we hold none.

vesselstring | null

The ship on this leg, TBN when not yet named, or null when the leg has no ship (see mode).

mode"water" | "feeder" | "rail" | "truck" | "barge" | "inland" | "unknown"

What the leg travels on: water and feeder are ships, rail, truck, barge and inland are not transshipment, unknown is a ship not yet named.

voyagestring | null

The line's voyage number for this leg, or null when not assigned.

servicestring | null

The line's own service name for this leg, or null when not given.

departurestring | null

Departure in the local time of this leg's port, with no offset.

arrivalstring | null

Arrival in the local time of this leg's port, with no offset.

routing_status"known" | "unknown"

known when is_transshipment is true or false, unknown when it is null.

Errors

Every refusal is { "ok": false, "error": { "code", "message", "parameter"? } }. The code is stable and safe to branch on, the message is a sentence for a person, and parameter names the input at fault where one input is at fault. No refusal or error is counted as a call. This endpoint never answers 404. A lane with nothing in the window, or a filter that matches nothing, is not an error: it answers 200 with an empty sailings list, which is a true answer about the filter rather than about the lane, and is not counted either.

MISSING_PARAMETER400

origin or destination was not given. `parameter` names the missing half, and neither when both are absent.

INVALID_DATE_FORMAT400

from is not a calendar date as YYYY-MM-DD, is not a real date (2026-02-30), carries a time or an offset, is more than a century ahead, or was given twice. `parameter` is from.

DATE_IN_PAST400

from is before today UTC. Schedules are forward-looking, so a past window is refused rather than quietly returning nothing. `parameter` is from.

INVALID_WEEKS400

weeks is not a window we can honour, or was given twice. `parameter` is weeks.

INVALID_SCAC400

A value in carrier is not four characters of capitals and digits. The message lists the offending values, clipped. `parameter` is carrier.

INVALID_TRANSSHIPMENT400

transshipment is something other than true or false. Deliberately strict: 1, yes and TRUE are refused rather than half-accepted. `parameter` is transshipment.

INVALID_CHANGED_SINCE400

changed_since is not a date or an instant in the formats above, is not a real date or time, is before 1970-01-01, or was given twice. `parameter` is changed_since.

CHANGED_SINCE_IN_FUTURE400

changed_since is later than now. Refused rather than answered with an empty list, which would read as a lane that never changes. `parameter` is changed_since.

INVALID_LIMIT400

limit is not a whole number from 1 to 500. `parameter` is limit.

INVALID_CURSOR400

cursor cannot be read. Start the lane again without it. `parameter` is cursor.

BAD_REQUEST400

A query we refuse before reading anything, free.

UNAUTHORIZED401

The key is missing, unknown, revoked or past its own expiry date. Not counted.

FORBIDDEN403

SchedulesMCP is not connected to your account. Not counted.

ACCESS_EXPIRED403

FORBIDDEN: the account has no Schedules access.

QUOTA_EXCEEDED429

QUOTA_EXCEEDED: the account's call quota for the month, or the key's daily limit, is spent.

RATE_LIMITED429

Too many requests in a short window. Wait Retry-After seconds. Not counted.

DB_ERROR500

The read failed on our side. Nothing was filtered out, so a retry is safe.

SERVICE_UNAVAILABLE503

Access could not be checked just now, so the request was not run. Retry after Retry-After. Not counted.

Per-line status: carriers

Each line gets a status, so zero sailings is no longer ambiguous: no_service (does not sail this window), timeout or failed (asked, no answer), not_attempted (not confirmed for this window), not_supported (no source). Check it before telling a person there are no sailings.

Is the answer complete: complete

true: the live search ran and every listed line is ok, no_service or not_supported. false: some line's answer may be incomplete (its status says which), or the live search did not run (never with transshipment) or was held back by our limits.

Is the routing known: routing_status

known: we can tell whether the box changes ship (direct, or via a named hub). unknown: we cannot, and is_transshipment is null.

Every routing a line publishes: routings=all

Adds the other routings the line publishes for the same departure, each marked is_alternative; without it the answer is unchanged. Use it to check ETD and ETA against the line's site or to choose a connection; priced as a normal search, and transshipment filters each routing on its own legs.

curl 'https://api.schedulesmcp.com/public/schedules?origin=CNSHA&destination=BRSSZ&weeks=4&transshipment=true&limit=2' \
  -H "Authorization: Bearer smcp_YOUR_API_KEY"
Response
{
  "ok": true,
  "data": {
    "origin": "CNSHA",
    "destination": "BRSSZ",
    "origin_name": "Shanghai",
    "destination_name": "Santos",
    "from": "2026-10-15T00:00:00",
    "to": "2026-11-12T00:00:00",
    "weeks": 4,
    "count": 2,
    "carriers": [
      {
        "carrier_code": "CMDU",
        "carrier_name": "CMA CGM",
        "count": 6,
        "latest_departure": "2026-11-09T16:00:00",
        "status": "ok",
        "checked_at": "2026-10-15T14:53:53.693+00:00"
      },
      {
        "carrier_code": "MSCU",
        "carrier_name": "Mediterranean Shipping Company (MSC)",
        "count": 4,
        "latest_departure": "2026-11-07T18:00:00",
        "status": "ok",
        "checked_at": "2026-10-15T13:27:49.497+00:00"
      },
      {
        "carrier_code": "HDMU",
        "carrier_name": "HMM",
        "count": 3,
        "latest_departure": "2026-11-04T12:00:00",
        "status": "ok",
        "checked_at": "2026-10-15T15:38:15.79+00:00"
      },
      {
        "carrier_code": "HLCU",
        "carrier_name": "Hapag-Lloyd",
        "count": 3,
        "latest_departure": "2026-11-09T13:00:00",
        "status": "ok",
        "checked_at": "2026-10-15T07:38:14.918+00:00"
      }
    ],
    "complete": false,
    "transshipment": true,
    "changed_since": null,
    "latest_departure_held": "2027-04-30T10:30:00",
    "as_of": "2026-10-15T18:30:05.234Z",
    "next": "https://api.schedulesmcp.com/public/schedules?origin=CNSHA&destination=BRSSZ&weeks=4&transshipment=true&limit=2&cursor=MjAyNi0xMC0xOFQwNzowMDowMCswMDowMHw5YjI1YjA1MC0yMjc3LTQ0MjQtOTA0NS03NTZhYzE0OGQ5M2F8MTc5MjA4OTAwNTc4MnxJVjFSZ08zcEc2MlI4TENEQ2Q2c01oU3lDUHpqVkZDV1pfODJOMVFNaUVBfDIwMjYtMTAtMTh-fjNhQmFQbkVQYXJP",
    "limit": 2,
    "via_port_names": {
      "COCTG": "Cartagena",
      "ESVLC": "Valencia"
    },
    "sailings": [
      {
        "sailing_id": "dc4ce3a5-76f8-403d-acfe-67d650531281",
        "carrier_code": "HLCU",
        "carrier_name": "Hapag-Lloyd",
        "service_name": "US2",
        "vessel_name": "OSAKA EXPRESS",
        "voyage_number": "640E",
        "published_departure": "2026-10-16T13:00:00",
        "published_arrival": "2026-12-05T13:00:00",
        "departure_precision": "minute",
        "arrival_precision": "minute",
        "cy_cutoff": "2026-10-15T07:00:00",
        "doc_cutoff": "2026-10-15T07:00:00",
        "vgm_cutoff": "2026-10-15T01:00:00",
        "is_transshipment": true,
        "transship_via": [
          "COCTG"
        ],
        "transit_days": 50,
        "route_legs": [
          {
            "leg": 1,
            "from": "CNSHA",
            "from_name": null,
            "to": "COCTG",
            "to_name": null,
            "vessel": "OSAKA EXPRESS",
            "mode": "water",
            "voyage": "640E",
            "service": "US2",
            "departure": "2026-10-16T13:00:00",
            "arrival": "2026-11-09T15:00:00"
          },
          {
            "leg": 2,
            "from": "COCTG",
            "from_name": null,
            "to": "BRSSZ",
            "to_name": null,
            "vessel": "JAZAN",
            "mode": "water",
            "voyage": "2644S",
            "service": "GS1",
            "departure": "2026-11-17T00:00:00",
            "arrival": "2026-12-05T13:00:00"
          }
        ],
        "routing_status": "known",
        "cutoffs": [
          {
            "type": "FCO",
            "at": "2026-10-15T07:00:00",
            "label": null
          },
          {
            "type": "DCO",
            "at": "2026-10-15T07:00:00",
            "label": null
          },
          {
            "type": "VCO",
            "at": "2026-10-15T01:00:00",
            "label": null
          }
        ],
        "cutoff_status": "published",
        "last_changed_at": "2026-09-29T07:44:18.780979+00:00",
        "retrieved_at": "2026-10-05T23:29:52.787+00:00",
        "vessel_imo": "9320697",
        "vessel": {
          "teu": 8164,
          "teu_estimated": false,
          "flag": "Liberia",
          "year_built": 2007,
          "length_m": 335.47
        }
      },
      {
        "sailing_id": "9b25b050-2277-4424-9045-756ac148d93a",
        "carrier_code": "MSCU",
        "carrier_name": "Mediterranean Shipping Company (MSC)",
        "service_name": "JADE SERVICE",
        "vessel_name": "MSC CELESTINO MARESCA",
        "voyage_number": "GJ640W",
        "published_departure": "2026-10-18T07:00:00",
        "published_arrival": "2026-12-16T01:00:00",
        "departure_precision": "minute",
        "arrival_precision": "minute",
        "cy_cutoff": "2026-10-13T22:00:00",
        "doc_cutoff": "2026-10-12T07:00:00",
        "vgm_cutoff": "2026-10-13T22:00:00",
        "is_transshipment": true,
        "transship_via": [
          "ESVLC"
        ],
        "transit_days": 59,
        "route_legs": [
          {
            "leg": 1,
            "from": "CNSHA",
            "from_name": "SHANGHAI",
            "to": "ESVLC",
            "to_name": "VALENCIA",
            "vessel": "MSC CELESTINO MARESCA",
            "mode": "water",
            "voyage": "GJ640W",
            "service": "JADE SERVICE",
            "departure": "2026-10-18T07:00:00",
            "arrival": "2026-11-25T18:30:00"
          },
          {
            "leg": 2,
            "from": "ESVLC",
            "from_name": "VALENCIA",
            "to": "BRSSZ",
            "to_name": "SANTOS",
            "vessel": "MSC MARIA MARILYN X",
            "mode": "water",
            "voyage": "MM647A",
            "service": "WEST MED TO SAEC",
            "departure": "2026-11-26T20:00:00",
            "arrival": "2026-12-16T01:00:00"
          }
        ],
        "routing_status": "known",
        "cutoffs": [
          {
            "type": "FCO",
            "at": "2026-10-13T22:00:00",
            "label": null
          },
          {
            "type": "DCO",
            "at": "2026-10-12T07:00:00",
            "label": null
          },
          {
            "type": "VCO",
            "at": "2026-10-13T22:00:00",
            "label": null
          },
          {
            "type": "X-RCO",
            "at": "2026-10-13T22:00:00",
            "label": null
          },
          {
            "type": "X-HCO",
            "at": "2026-10-07T00:00:00",
            "label": null
          }
        ],
        "cutoff_status": "published",
        "last_changed_at": null,
        "retrieved_at": "2026-10-15T13:27:49.497+00:00",
        "vessel_imo": "9930040",
        "vessel": {
          "teu": 21445,
          "teu_estimated": false,
          "flag": null,
          "year_built": 2023,
          "length_m": 399.99
        }
      }
    ]
  }
}