Schedules inside your system
Sailings with vessel, voyage number, ports of loading and discharge, departure and arrival dates, transit time and arrival terminal. Filters by carrier, vessel, ports and date range.
Integration
Container shipping data — sailing schedules, ocean carriers, fleet and services — straight into your system. Plain HTTP requests, JSON responses, one key in a header.
Why it matters
No more manual exports and copy-paste: data arrives in your system in a shape that is ready to process.
Sailings with vessel, voyage number, ports of loading and discharge, departure and arrival dates, transit time and arrival terminal. Filters by carrier, vessel, ports and date range.
Legal entity, country of registration, trade areas, directions, agents in Russia with contacts and terminals. A ready source for your counterparty records.
Vessels with IMO number, type, TEU capacity, deadweight, year built, age and flag. Useful for assessing a carrier capacity on a given trade.
Service identifiers, port rotations, countries of origin and destination. Lets you build automatic routing options for a required direction.
We keep the data up to date, you receive it with every request. Each response carries the date of the last update, so you can sync only what has actually changed.
A personal key, a daily request limit and per-section permissions. The remaining quota is shown in every response, so nothing gets cut off without warning.
Nearest departures for a route right inside your CRM, without searching carrier websites by hand.
Planned shipping dates in your ERP: the schedule is pulled in automatically and stays current.
Fleet and service data in your BI tool to assess capacity and trade dynamics.
A ready reference of carriers, ports and terminals for your internal services.
Getting started
From request to first response usually takes one business day.
Write to service@way-bill.ru with your company name, the data sections you need and an estimated number of daily requests. For companies we prepare a contract and an invoice.
We issue a personal key in the form wb_live_… and agree
on a daily limit and validity period. The key is shared once —
store it like a password.
Verify access on /v1/meta, then move on to the data
you need. Code samples in four languages are below.
Quick start
The key goes in the X-API-Key header. Nothing else is required.
curl -H "X-API-Key: YOUR_KEY" \
-H "Accept-Encoding: gzip" \
"https://api.way-billapi.ru/v1/schedule?line=FESCO&limit=5" import requests
BASE = "https://api.way-billapi.ru/v1"
HEADERS = {"X-API-Key": "YOUR_KEY"}
r = requests.get(f"{BASE}/schedule",
headers=HEADERS,
params={"line": "FESCO", "limit": 5},
timeout=20)
r.raise_for_status()
payload = r.json()
for row in payload["data"]:
print(row["vessel"], row["voyage"], row["portFrom"], "→", row["portTo"], row["etd"])
print("requests left:",
payload["meta"]["quota"]["limit"] - payload["meta"]["quota"]["used"]) const BASE = "https://api.way-billapi.ru/v1";
async function schedule(params) {
const url = new URL(BASE + "/schedule");
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
const res = await fetch(url, { headers: { "X-API-Key": "YOUR_KEY" } });
if (!res.ok) {
const err = await res.json();
throw new Error(err.error.code + ": " + err.error.message);
}
return res.json();
}
schedule({ line: "FESCO", limit: 5 }).then(p => console.table(p.data)); <?php
$base = "https://api.way-billapi.ru/v1";
$url = $base . "/schedule?" . http_build_query(["line" => "FESCO", "limit" => 5]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "gzip",
CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_KEY"],
CURLOPT_TIMEOUT => 20,
]);
$body = curl_exec($ch);
curl_close($ch);
$payload = json_decode($body, true);
foreach ($payload["data"] as $row) {
echo $row["vessel"], " ", $row["voyage"], " ", $row["etd"], PHP_EOL;
} Reference
API version v1. Every section is available over HTTPS and via GET only.
A full request URL is the base URL plus the section name, for example
https://api.way-billapi.ru/v1/lines. Plain HTTP requests
are redirected to HTTPS automatically.
The key is passed in a header:
X-API-Key: wb_live_a7f3c9d2e1b48605 Authorization: Bearer <key> is supported as well —
convenient if your HTTP client is built around that scheme.
A request without a key returns 401; an unknown
or revoked key returns 403.
A successful response always has the same shape: payload in data, service information in meta.
{
"data": [ … ],
"meta": {
"total": 1284,
"limit": 100,
"offset": 0,
"updated": "2026-08-23",
"quota": { "limit": 5000, "used": 132 }
}
} total is how many records matched the filters in total,
updated is the date the data was last refreshed on our side,
quota is your daily limit and current usage.
Pagination: limit (100 by default, 1000 maximum) and
offset. Keep fetching pages while
offset + limit is less than total.
The daily limit belongs to the key and resets at midnight UTC.
Current usage is shown in meta.quota of every response,
so no separate call is needed.
Once the limit is reached you get 429 with code
daily_limit. If the limit is consistently too low,
write to us and we will raise it.
/v1/meta Update dates and data volumes A lightweight call to verify access and monitor data freshness. No parameters.
{
"data": {
"schedule": { "updated": "2026-08-23", "voyages": 1284 },
"lines": { "updated": "2026-08-17", "total": 131, "active": 70 },
"vessels": 248,
"services": 125
}
} /v1/schedule Sailing schedule | Parameter | Type | Description |
|---|---|---|
line | string | Carrier name, exact match |
vessel | string | Vessel name |
voyage | string | Voyage number |
portFrom | string | Port of loading, substring match |
portTo | string | Port of discharge, substring match |
terminal | string | Arrival terminal |
etdFrom | date | Departure on or after, format YYYY-MM-DD |
etdTo | date | Departure on or before |
limit, offset | number | Pagination |
GET /v1/schedule?portTo=Novorossiysk&etdFrom=2026-09-01&limit=2
{
"data": [
{
"line": "AKKON LINES", "vessel": "LIDER PERIHAN", "voyage": "2536W",
"portFrom": "Gebze", "etd": "2026-09-02",
"portTo": "Novorossiysk", "terminal": "NUTEP",
"eta": "2026-09-06", "transit": "4"
}
],
"meta": { "total": 314, "limit": 2, "offset": 0, "updated": "2026-08-23" }
} /v1/lines Ocean carrier directory | Parameter | Type | Description |
|---|---|---|
q | string | Search by name and legal entity |
basin | string | Trade area. Values come in Russian: Балтийский (Baltic), Азово-Черноморский (Azov–Black Sea), Дальневосточный (Far East), Каспийский (Caspian), Арктический (Arctic) |
active | 1 or 0 | Active carriers only, or discontinued only |
limit, offset | number | Pagination |
The list returns short records: name, slug, legal entity, country, trade areas, status and fleet statistics.
/v1/lines/{slug} Full carrier record
The slug comes from the slug field in the carrier list,
for example /v1/lines/fesco. Returns description, address,
directions, agents with contacts, services and the full vessel list.
If the carrier is not found — 404.
/v1/vessels Fleet | Parameter | Type | Description |
|---|---|---|
line | string | Fleet of a single carrier |
imo | string | A specific vessel by IMO number |
limit, offset | number | Pagination |
{
"data": [
{ "line": "FESCO", "name": "FESCO SOFIA", "imo": "9237503",
"type": "Container Ship", "teu": 2702, "dwt": 33745,
"built": "2002", "age": 24, "flag": "Russia" }
]
} /v1/services Services and routings | Parameter | Type | Description |
|---|---|---|
line | string | Services of a single carrier |
countryFrom | string | Country of origin |
pod | string | Port of discharge |
limit, offset | number | Pagination |
/v1/positions Vessel positions · on request
Live vessel coordinates, speed and course. This section is provided
on a case-by-case basis: the data comes from an external AIS provider
and redistribution is governed by their terms. When access is off,
the section returns 503 with an explanation.
Errors use the same envelope as data, but with an error key:
{ "error": { "code": "daily_limit", "message": "Daily request limit reached." } } | HTTP code | code | What happened |
|---|---|---|
| 401 | no_key | The key header was not sent |
| 403 | bad_key | Key is unknown or revoked |
| 403 | key_expired | Key has expired |
| 403 | scope_denied | Key has no access to this section |
| 404 | not_found | Unknown path or carrier not found |
| 405 | method_not_allowed | A method other than GET was used |
| 429 | daily_limit | Daily limit reached |
| 503 | positions_disabled | Positions section is not enabled |
| 500 | internal | Internal error, retry later |
Accept-Encoding: gzip header cuts response size by roughly 84 percent.meta.updated and avoid pulling the same payload in a loop.limit=1000 saves calls when you process the whole set anyway.Questions
Sailing schedules — daily. Carrier, fleet and service directories — as carriers publish changes, usually several times a month. The exact date of the last update for each set comes in meta.updated.
No. These are plain HTTP requests with a single header, callable from any language and even from the browser console. Samples for four languages are above.
Yes. Every key has its own list of permitted sections. A key may open the schedule only — calls to the rest return 403 scope_denied.
Requests return 429 until the next UTC day begins. Access is not blocked and needs no restoring — wait for the counter to reset or ask us to raise the limit.
Write to us — we revoke the old key and issue a new one within a business day. Revocation takes effect immediately.
Within v1 we never remove or rename existing fields. New fields may appear — write your parser so that it ignores unknown ones.
Tell us about your use case — we will suggest the right sections and limit, and issue a test key.