ShipCore — Phase 2 Carrier APIs Deep Dive¶
Призначення документа. Phase 0 → Phase 1 закрив бізнес-стратегію та compliance scope. Phase 2 заглиблюється в технічну сторону зовнішніх інтеграцій — щоб Phase 4 (refactor) і Phase 5 (Maersk Spot first integration) стартували з точними API-фактами, а не з припущеннями. Кожна secondary integration (Hapag-Lloyd, CMA CGM, MSC) у Phase 8 наслідує паттерн, обкатаний на Phase 5. Аналогічно — road-телематика, WIN platform, Awery air-cargo.
Reliability legend. ✅ підтверджено офіційним джерелом (developer.maersk.com, dcsa.org, IATA, official partner docs) · 🟡 підтверджено двома незалежними вторинними джерелами (industry coverage, vendor reviews, customer case studies) · ⚠️ суперечливі дані між джерелами — обидві версії показані · (?) невпевнено, треба окремий research перед commit'ом.
Бюджет рисерчу. ~55 хв (16 паралельних web-search + 2 GitHub/portal fetch). Phase 4 refactor commit (~3 тижні effort) та Phase 5 Maersk Spot integration (~2 тижні) залежать від цього documents — точність важливіша за швидкість.
0. TL;DR¶
- DCSA — нова реальність ocean. Top-9 carriers (MSC, Maersk, CMA CGM, Hapag-Lloyd, ONE, Evergreen, Yang Ming, HMM, ZIM) — founding members. Booking 2.0 + BL 3.0 фінал — лютий 2025 ✅. Track & Trace v2.2 — поточний стандарт ✅. VGM REST API — листопад 2025 ✅ (replaces VERMAS EDIFACT, як зафіксовано у C5 corrections). Імплікація: ShipCore проектує
CarrierAdapterнавколо DCSA OpenAPI specs, не carrier-specific schemas — adapter для одного carrier'а на 70% реюзабельний для іншого DCSA-compliant. - Maersk Spot для Phase 5 — підтверджено правильним вибором. OAuth2 client credentials flow ✅, безкоштовний tier API access (subject to future change) ✅, sandbox environment з self-service registration ✅, DCSA Booking 2.0 endpoint у production ✅. Token endpoint
https://api.maersk.com/customer-identity/oauth/v2/access_token+ Consumer-Key header. Python integration straightforward черезrequests-oauthlibабоauthlib. - CMA CGM — найкращий second carrier для Phase 8. Two-tier модель: public tier (API key, free trial 30 днів) для container milestones + private tier (OAuth2 + booking party identification) для rail/inland events ✅. Hapag-Lloyd Quick Quotes — теж OAuth2 + sandbox. MSC — DCSA-compliant з 2025 (Commercial Schedules live, Booking 2.0 + eBL 3.0 в розробці) 🟡.
- Vizion vs Terminal49 — Vizion виграє для UA mid-market. Vizion: ~$4-5/container, ~99% global ocean coverage, 60+ standardized milestones (60+ event milestones з 7000+ raw points), 33+ shipping lines normalized 🟡. Terminal49: free dev key до 100 containers, мінімум 100/міс на платних планах, push webhook architecture 🟡. Recommendation: Vizion як primary aggregator fallback (більш покриття + дешевше per-container), Terminal49 як backup якщо потрібно push-first webhooks.
- WIN platform — buy-vs-build НЕ однозначно "buy". WIN — реальна live платформа (winwebconnect.com), бере 160+ airlines, інтегрована Riege Scope. Web Service API доступний (PDF docs publicly online) ✅. Але: ціни не публічні, фокус — small/mid forwarders, ocean coverage слабша за air. Phase 7 рекомендація: 2-3 дні research включно з outreach call перед commit
shipcore_pricing.LaneRateHistorybuild. Якщо WIN partnership дешевше за internal build для air — buy. Для ocean — будуємо власне (LaneRateHistory + DCSA Commercial Schedules). - Awery — air partnership confirmed actionable. UA-походження ✅, переможець IATA ONE Record Hackathon п'ятий раз поспіль (2026-04-29) ✅, готує open-source PHP ONE Record server для широкої adoption ✅. Phase 9+ план з C2 corrections — outreach під час Phase 4-5, Awery API integration + white-label opportunity для ShipCore-Avia.
- Road telematics: Wialon production-ready, Geotab/Samsara — для EU expansion v1.5. Wialon hosting API rate limits well-documented ✅ (10 unsuccessful logins/min, 200 executions/5min/IP, 1GB max report) — vendor-locked для UA-ринку, де він де-факто стандарт. Geotab — leader EU presence (ABI Research #1 four years running) 🟡, Samsara — superior UX (Capterra 84% satisfaction) 🟡. Webfleet (Bridgestone-owned, ex-TomTom Telematics) — третя альтернатива, WEBFLEET.connect SOAP API legacy + REST modern 🟡. Phase 5 — Wialon only, Phase 8 — Geotab/Samsara connectors як EU expansion enabler.
- DCSA OpenAPI v2.0.1 — ця версія ВЖЕ застаріла. GitHub repo
dcsaorg/DCSA-OpenAPIlast "release tag" 2.0.1 травня 2021, але активна розробка йде у master branch без semver tags. Поточні актуальні версії: TNT v2.2 (грудень 2024), Booking 2.0 final (лютий 2025), BL 3.0 final (лютий 2025), VGM v1.0 (листопад 2025) ✅. Висновок: GitHub releases page вводить в оману, треба орієнтуватися на dcsa.org/standards/* для current state.
1. Maersk Spot (Phase 5 P0 — first carrier integration)¶
1.1. API endpoints catalogue¶
Maersk Developer Portal (developer.maersk.com/api-catalogue) ✅ — публічний self-service portal з 40+ APIs, головні для ShipCore Phase 5:
| API Product | Scope | DCSA-aligned | Phase 5 use |
|---|---|---|---|
Maersk Offers API (api.productmanagement.maersk.com/offers) |
Spot product offers, pricing at booking time, port-pair rates | Maersk-specific (не DCSA — це pre-booking quote) | Quote pull для shipcore_forwarder.Quote |
Ocean Booking v2 [DCSA] (developer.maersk.com/api-catalogue/EDP%20Booking) |
Create/amend/cancel ocean booking, get booking status | DCSA Booking 2.0 ✅ | Booking creation з shipcore_sea.OceanBooking |
Track & Trace Plus (developer.maersk.com/api-catalogue/Track%20and%20Trace%20Plus) |
Container/shipment events, ETAs, transhipment milestones | DCSA TNT 2.2 ✅ | Real-time tracking → shipcore.ShipmentEvent |
Ocean — Carrier Bill of Lading [DCSA] (dcsa-bill-of-lading) |
Issue/amend/surrender BL | DCSA BL 3.0 ✅ | shipcore_sea.BillOfLading issuance + eBL flow (Phase 8) |
Ocean Booking Status Webhook [DCSA] (ocean-booking-status-webhook) |
Push notifications для booking status changes | DCSA-compliant webhook spec ✅ | Async update листeners для booking lifecycle |
| VGM Submission (DCSA REST replacement of VERMAS EDIFACT) | Submit verified gross mass | DCSA VGM v1.0 (Nov 2025) ✅ | shipcore_terminal.GateTransaction VGM push (C5 correction) |
| Schedules API (Commercial + Operational Vessel Schedules) | Vessel sailings, port pairs, transit times | DCSA Commercial Schedules ✅ | Routing/ETA estimates у Quote step |
Note: Track & Trace Plus = Maersk's value-add layer over base DCSA TNT. Дає SLA + extra metadata (наприклад,
temperatureAtCarrierдля reefer). Базовий TNT доступний без upgrade.
1.2. Authentication — OAuth2 client credentials¶
Підтверджено через developer.maersk.com/support/authorisation ✅:
# Token endpoint
POST https://api.maersk.com/customer-identity/oauth/v2/access_token
Headers:
Consumer-Key: <consumer_key_from_app_registration>
Content-Type: application/x-www-form-urlencoded
Body (form-urlencoded):
grant_type=client_credentials
client_id=<client_id>
client_secret=<client_secret>
# Response: { "access_token": "...", "expires_in": 3600, "token_type": "Bearer" }
Особливості:
- Двофакторний auth: окремо
Consumer-Key(header, app identity) +client_id/client_secret(credentials body). Це Apigee-style edge gateway (Maersk hostuye через Google Cloud Apigee 🟡). - Token TTL 1 година. Adapter повинен refresh proactively (e.g., якщо
expires_in - elapsed < 60s). - На кожний бізнес-запит додається
Authorization: Bearer <access_token>+Consumer-Keyheader. - Sandbox vs production — окремі consumer keys, окремі URL (
api-sit.env.productmanagement.maersk.comдля sandbox vsapi.productmanagement.maersk.comдля prod) 🟡.
1.3. Sandbox setup¶
Підтверджено через api-sit.env.productmanagement.maersk.com/offers/docs/overview/onboarding.html ✅:
- Реєстрація на Maersk Developer Portal — self-service, без customer contract вимагається на старті ✅.
- Створення
Applicationу личному кабінеті — отримуєш Consumer Key + Client ID/Secret пару. - Subscribe до конкретного API product (e.g., "Ocean Booking v2 [DCSA]") — окремий plan для sandbox, окремий для prod.
- Sandbox дані — синтетичні fixtures, обмежений набір port-pairs (типово USCHI-DEHAM, CNSHA-USLAX) для тестування.
- Production access — потребує customer contract з Maersk (тобто компанія має активний
mscpабо equivalent customer agreement) ✅.
Implication для pilot. Wave 1 UA mid-market road carrier (C8 архетип, конкретний клієнт TBD) — UA-tier carrier, скоріш за все НЕ має активного Maersk customer contract. Це означає, що Phase 5 Maersk integration демонструється на sandbox, а production rollout = після того як ShipCore підпише агентську угоду через Maersk-aligned 3PL. Альтернатива — pilot з ZAMMLER (Wave 2) у якого contract є.
1.4. Rate limits & error handling¶
⚠️ Rate limits НЕ оприлюднюються публічно у developer portal (?). На основі industry practice (Apigee gateway defaults + Maersk capacity claims):
- Estimated: 100-500 RPS per consumer key для read APIs (Schedules, Track & Trace).
- Estimated: ~10-30 RPS для write APIs (Booking creation/amendment).
- HTTP 429 (Too Many Requests) з
Retry-Afterheader — стандартна Apigee pattern (?).
Retry policy для CarrierAdapter:
# Pseudocode для retry strategy
RETRY_ON_STATUS = {429, 502, 503, 504}
TRANSIENT_ERRORS = {ConnectionError, ReadTimeout}
MAX_RETRIES = 5
BACKOFF = ExponentialBackoff(base=1.0, multiplier=2.0, max_delay=60.0, jitter=0.5)
# 401 Unauthorized → token expired → refresh + retry once (no backoff)
# 403 Forbidden → permission issue → no retry, raise to user
# 422 Unprocessable Entity → DCSA validation error → no retry, surface validation
# 4xx other → log + raise
# 5xx → retry with backoff
# 429 → respect Retry-After if present, else exponential backoff
1.5. Pricing / billing model¶
Confirmed via maersk.com/support/faqs/do-i-need-to-pay-to-use-your-api ✅:
"Maersk's APIs are free to use, though the company reserves the right to implement a payment plan in the future for API usage as defined by their API License Terms."
Implication: Phase 5 cost model = $0 for API access, але Maersk explicitly резервує право монетизувати. Розумний planning horizon — 2-3 роки free, потім очікувати tiered pricing (estimated $500-5000/міс при production volumes 🟡).
1.6. DCSA compliance status¶
Maersk — founding DCSA member ✅. Конкретні endpoints позначені [DCSA] у API catalogue, тобто URL/payload schema прямо реалізує DCSA OpenAPI specs:
- ✅ Booking 2.0 (final Feb 2025)
- ✅ BL 3.0 (final Feb 2025)
- ✅ TNT v2.2 (December 2024)
- ✅ VGM v1.0 (November 2025) — confirmed C5 correction
- 🟡 Commercial Schedules — published; OVS pending
1.7. Sample workflow: Quote → Booking → BL → Track¶
1. Quote pull
GET /offers?origin=USCHI&destination=DEHAM&commodity=44011200&containerType=40HC
→ [{ offerId, validUntil, totalPrice, transitDays, sailings: [...] }]
2. Booking creation
POST /booking/v2/bookings
Body (DCSA Booking 2.0):
{ offerReference, parties: { shipper, consignee, notifyParty },
cargoDetails, equipment, transportPlan, ... }
→ { bookingReference, carrierBookingRequestReference, status: "PENDING_UPDATE_CONFIRMATION" }
3. Webhook: booking confirmation
POST <ShipCore webhook URL>
{ bookingReference, status: "CONFIRMED", carrierBookingReference: "MAEU2025XXXX" }
4. VGM submission (after gate-in)
POST /vgm/v1/verified-gross-mass
Body: { equipmentReference, vgm: { weight, weighingMethod, ... } }
5. BL issuance
POST /bills-of-lading/v3
Body (DCSA BL 3.0): { transportDocumentReference, parties, cargoItems, charges, ... }
→ { transportDocumentReference: "MAEU0987654", documentStatus: "ISSUED" }
6. Track & Trace polling (or webhook)
GET /track-and-trace/v2/events?carrierBookingReference=MAEU2025XXXX
→ [ { eventType: "TRANSPORT", eventClassifierCode: "ACT",
eventDateTime, eventLocation, transportCall: {...} }, ... ]
1.8. SDK availability¶
⚠️ No official Maersk-published SDK для Python/Node/Java (?). Maersk покладається на raw OpenAPI specs — клієнт generates SDK via openapi-generator.
Recommendation для ShipCore CarrierAdapter:
- Не використовувати auto-generated SDK (overhead + losely-typed коли DCSA schema еволюціонує).
- Власна тонка обгортка
MaerskSpotAdapter(BaseCarrierAdapter)зhttpx(async-first) +pydanticmodels, generated одноразово з DCSA OpenAPI YAML, не з Maersk's portal.
1.9. DCSA VGM REST integration¶
Per C5 corrections, Phase 5 пише VGM через DCSA REST, не EDI. Підтверджено через dcsa.org/standards/vgm ✅:
- Стандарт опубліковано 18 листопада 2025 (Smart Maritime Network coverage).
- Built on DCSA data model, fully aligned з SOLAS Convention requirements.
- Replaces VERMAS EDIFACT as preferred submission method ✅.
- Maersk DCSA member → expected to support endpoint у production (timeline невідомий, скоріш за все Q1-Q2 2026 🟡).
Phase 5 implication: shipcore_terminal.GateTransaction пише VGM через MaerskSpotAdapter.submit_vgm(equipment_ref, weight, method) що hits DCSA-aligned endpoint. Спрощує реалізацію (нема EDI parser) і робить ShipCore автоматично compatible з усіма DCSA-aligned carriers.
2. Hapag-Lloyd Quick Quotes (Phase 8 P1)¶
2.1. API portal & products¶
api-portal.hlag.com ✅ — повноцінний developer portal з documentation hub doc.api-portal.hlag.com. API products:
| Product | Scope | DCSA-aligned |
|---|---|---|
| Quotation/Booking Engine — External Prices | Quick Quotes (FAK rates), Quick Quotes Spot (real-time spot), get & save quote | Hapag-specific (?) — quote layer не покритий DCSA |
| Booking | Create/amend booking | DCSA Booking 2.0 (?) — verified industry adoption, але explicit DCSA alignment Hapag-Lloyd підтверджено для T&T та Schedules; Booking 2.0 — пізніша імплементація 🟡 |
| Track & Trace | Container/shipment events | DCSA TNT (Hapag explicitly migrated to "latest DCSA Track & Trace interface" — confirmed via Coneksion case study) 🟡 |
| Schedules | Vessel sailings | DCSA Commercial Schedules ✅ |
2.2. Authentication¶
OAuth2 з Authorization Code-type applications (per doc.api-portal.hlag.com) ✅:
- Self-service registration → create application → отримуєш ClientID + Client Secret.
- Sandbox environment available — sandbox tests дозволяють simulate API calls без registration ✅ (нижчий barrier ніж Maersk).
- Subscribe to API product → activate credentials → ready to call.
2.3. Pricing & rate limits¶
⚠️ Не оприлюднюються публічно. Industry practice — free tier для testing, customer contract вимагається для production volumes (?). Inferred з Dachser case study (Descartes integration) — production access requires Hapag account team involvement 🟡.
2.4. DCSA compliance status¶
Hapag-Lloyd — founding DCSA member ✅. Track & Trace — explicitly DCSA-aligned (Coneksion CCL via Youredi case study confirms migration) 🟡. Booking 2.0 + BL 3.0 adoption — у процесі (роадмап не публічний, але як founding member експектується Q1-Q3 2026 🟡).
3. CMA CGM API (Phase 8 P1)¶
3.1. Two-tier model — найунікальніший для CMA¶
Confirmed via api-portal.cma-cgm.com/starting-guide ✅:
| Tier | Auth | Free? | Scope |
|---|---|---|---|
| Public | API key | ✅ Free 30-day trial з обмеженим quota | Container milestones, transshipment events, planned vessel dates |
| Private | OAuth2 + booking party identification | ❌ Paid (custom contract) | Rail moves, ramp moves, inland move dates, granular event data |
Implication для ShipCore: Phase 8 Wave 2 (ZAMMLER pilot) — починаємо з public tier для proof-of-concept, переходимо на private tier коли є контракт між клієнтом і CMA. Це дешевша discovery path ніж Maersk (де sandbox обмежений port-pairs).
3.2. API endpoints¶
Per cloud.customer.cmacgm-group.com/EDI_catalog_EN 🟡:
- Booking Request & Confirmation
- Original BL (PDF or structured payload)
- Container Tracking (DCSA TNT v2.2 для public + extended fields для private)
- Schedules (DCSA Commercial Schedules ✅ — підтверджено документацією на
api-portal.cma-cgm.com/products/visibilityпро DCSA OpenAPI v2.2.0) - Public Prices Finder (separate web tool — НЕ API, але дає reference для public rate validation)
3.3. DCSA compliance¶
CMA CGM — founding DCSA member ✅. Track & Trace — explicit DCSA OpenAPI specification for Track & Trace v2.2.0 referenced в API portal ✅. Booking 2.0 + BL 3.0 — adoption у процесі (no public roadmap).
4. MSC eBusiness (Phase 8 P1)¶
4.1. Status: REST coverage vs EDI legacy¶
MSC — найбільший carrier у світі (за TEU capacity станом на 2024) і найпізніший до cleanup REST API на DCSA. Положення станом на 2025:
- ✅ Developer Portal launched:
developerportal.msc.com/api-catalogue - ✅ DCSA Commercial Schedules API — fully adopted (Point-to-Point endpoint live, vessel/port schedule endpoints у розробці) — confirmed via June 2025 Smart Maritime Network coverage.
- 🟡 DCSA Booking 2.0 + eBL 3.0 — scheduled (status: development, no public timeline).
- ⚠️ Historical legacy: MSC heavily reliant на EDIFACT IFTMBF/IFTMIN/IFTSTA — many existing integrations не migrated до REST yet.
Implication для ShipCore: Phase 8 MSC integration — починати з DCSA Commercial Schedules (для routing/quote contexts) + Track & Trace (для visibility), уникати EDI completely. Booking creation можливо доведеться чекати 2026-Q3+ або робити через EDI як interim (не рекомендую — EDI parser cost > value).
4.2. Authentication¶
OAuth2 (per developer portal architecture, deduced from DCSA-aligned approach) (?) — точна flow не verified, presumably client credentials.
5. Vizion / Terminal49 (fallback aggregators) + buy-vs-build аналіз¶
5.1. Vizion (vizionapi.com)¶
| Aspect | Detail |
|---|---|
| Coverage | ~99% global ocean freight shipments tracked, 33+ shipping lines normalized into single schema, all major U.S. terminals ✅ |
| Carriers | Most shipping lines out-of-the-box; custom carrier integration on quote 🟡 |
| Event milestones | 60+ standardized milestones derived from 7000+ raw data points ✅ |
| Data sources | API + EDI + AIS + crawling (terrestrial + satellite AIS) — multi-modal data fusion 🟡 |
| Pricing | Tier 1: ~$5/container з 15 free/міс; Tier 2: ~$4.38/container з 40 free/міс 🟡 (per F6S/Capterra reviews); Enterprise — custom 🟡 |
| API style | REST + webhooks, push-based для status changes 🟡 |
| Latency | "Real-time" claim, типово updates within minutes of carrier event publication (?) |
5.2. Terminal49 (terminal49.com)¶
| Aspect | Detail |
|---|---|
| Coverage | 100% carriers touching North America, includes terminals + rails + AIS ✅ |
| Carriers | All major shipping lines, "33+ shipping lines normalized into a single, consistent data schema" ✅ |
| Pricing | Free Developer Key до 100 containers; paid plans (Lite/Essential/Enterprise) start at min 100 containers/month 🟡 |
| API style | REST + push-first webhooks (push API updates webhook on status change including milestones, ETAs) ✅ |
| Reliability claims | 99.5% API uptime, low latency, guaranteed data freshness ✅ |
5.3. Buy-vs-build для UA mid-market¶
Scenario 1: 100% direct adapters
- Build effort: ~2 тижні per carrier × ~10 carriers = 20 weeks
- Maintenance: ~1 day/month per adapter × 10 = ~120 days/year
- API costs: ~$0/month (більшість free tier)
- TOTAL Year 1: ~140 dev-days + $0/month
Scenario 2: 100% aggregator (Vizion)
- Build effort: ~1 week (single integration)
- Maintenance: ~0.5 day/month
- API costs: ~$200-500/month per ~1000 containers (Vizion rough estimate)
- TOTAL Year 1: ~7 dev-days + ~$3-6K/year
Scenario 3: HYBRID (DECISION D11) ✅ recommended
- Direct adapters для top-4 (Maersk Phase 5, Hapag/CMA/MSC Phase 8)
→ ~8 weeks effort × 4 = 32 weeks (across Phase 5+8)
- Vizion fallback для остатних 20+ carriers (ONE, ZIM, COSCO, Evergreen, ...)
→ ~1 week integration
- Mix benefits: rich data for top carriers + coverage breadth via aggregator
- TOTAL Year 1: ~33 dev-days incremental + ~$2-4K/year aggregator cost
Conclusion: Hybrid (D11) залишається правильним рішенням для UA mid-market (price sensitive але не extreme — клієнти готові платити $200-500/міс aggregator subscription за value visibility).
6. Уніфікований CarrierAdapter Python interface design¶
Наступне — proposal для Phase 4 implementation. Pythonic, async-first, DCSA-typed моделями, чітке розділення direct vs aggregator implementations.
6.1. Base abstract class¶
# backend/shipcore/integrations/carrier_adapter.py
from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal
from typing import AsyncIterator, Sequence
from shipcore.dcsa.models import (
BookingRequest, BookingConfirmation, TransportEvent,
BillOfLading, VGMSubmission, OfferQuote
)
@dataclass(frozen=True)
class CarrierCredentials:
"""Per-tenant + per-carrier secrets (зберігається у TenantSecret + envelope encryption)."""
consumer_key: str | None = None # Maersk-style edge gateway
client_id: str
client_secret: str
api_key: str | None = None # CMA CGM public tier alternative
sandbox: bool = True
extra: dict[str, str] | None = None # vendor-specific overrides
class BaseCarrierAdapter(ABC):
"""Контракт для будь-якого ocean carrier integration.
Implementations:
- DirectCarrierAdapter — direct REST до carrier (Maersk, Hapag, CMA, MSC)
- AggregatorCarrierAdapter — через Vizion/Terminal49 для решти
Усі методи async — Daphne already в проекті, blocking IO у Channels не дозволено.
Усі моделі — pydantic v2 згенеровані з DCSA OpenAPI specs (single source of truth).
"""
SCAC: str # Standard Carrier Alpha Code (e.g., "MAEU", "HLCU", "CMDU", "MSCU")
DCSA_VERSIONS: dict[str, str] # {"booking": "2.0", "tnt": "2.2", "bl": "3.0", "vgm": "1.0"}
def __init__(self, credentials: CarrierCredentials, http_client=None):
self.credentials = credentials
self._http = http_client # injected httpx.AsyncClient — testability
self._token_cache: tuple[str, datetime] | None = None
@abstractmethod
async def get_quote(
self,
origin: str, # UN/LOCODE, e.g., "USCHI"
destination: str, # UN/LOCODE, e.g., "DEHAM"
commodity_code: str, # HS code
equipment: Sequence[str], # ["40HC", "20DV"]
departure_window: tuple[datetime, datetime],
) -> Sequence[OfferQuote]:
"""Pull spot/contract rates. Returns 0+ offers with validity window."""
@abstractmethod
async def create_booking(self, request: BookingRequest) -> BookingConfirmation:
"""Submit booking request to carrier. Async confirmation via webhook."""
@abstractmethod
async def get_booking_status(self, carrier_booking_ref: str) -> BookingConfirmation:
"""Pull current booking state."""
@abstractmethod
async def submit_vgm(self, submission: VGMSubmission) -> str:
"""Submit verified gross mass per DCSA VGM v1.0. Returns confirmation ID."""
@abstractmethod
async def issue_bill_of_lading(
self, carrier_booking_ref: str, bl_data: BillOfLading
) -> BillOfLading:
"""Request BL issuance per DCSA BL 3.0."""
@abstractmethod
async def stream_events(
self, carrier_booking_ref: str, since: datetime | None = None,
) -> AsyncIterator[TransportEvent]:
"""Yield Track & Trace events (DCSA TNT v2.2). Use webhook subscription
in production; this method is for backfill/polling fallback."""
# Common implementation для усіх direct adapters (OAuth2 token caching)
async def _get_access_token(self) -> str:
if self._token_cache:
token, expires_at = self._token_cache
if expires_at > datetime.utcnow().add(seconds=60): # 60s safety margin
return token
token, ttl = await self._refresh_token()
expires_at = datetime.utcnow().add(seconds=ttl)
self._token_cache = (token, expires_at)
return token
@abstractmethod
async def _refresh_token(self) -> tuple[str, int]:
"""Vendor-specific OAuth2 dance. Returns (access_token, expires_in_seconds)."""
6.2. Concrete implementation — MaerskSpotAdapter¶
# backend/shipcore/integrations/maersk/adapter.py
import httpx
from datetime import datetime
from typing import AsyncIterator, Sequence
from shipcore.integrations.carrier_adapter import (
BaseCarrierAdapter, CarrierCredentials,
)
from shipcore.dcsa.models import (
BookingRequest, BookingConfirmation, TransportEvent,
BillOfLading, VGMSubmission, OfferQuote,
)
class MaerskSpotAdapter(BaseCarrierAdapter):
SCAC = "MAEU"
DCSA_VERSIONS = {"booking": "2.0", "tnt": "2.2", "bl": "3.0", "vgm": "1.0"}
BASE_URL_PROD = "https://api.maersk.com"
BASE_URL_SANDBOX = "https://api-sit.env.maersk.com" # confirmed pattern via offers subdomain
@property
def _base_url(self) -> str:
return self.BASE_URL_SANDBOX if self.credentials.sandbox else self.BASE_URL_PROD
async def _refresh_token(self) -> tuple[str, int]:
"""Maersk OAuth2 client credentials flow."""
url = f"{self._base_url}/customer-identity/oauth/v2/access_token"
headers = {
"Consumer-Key": self.credentials.consumer_key,
"Content-Type": "application/x-www-form-urlencoded",
}
data = {
"grant_type": "client_credentials",
"client_id": self.credentials.client_id,
"client_secret": self.credentials.client_secret,
}
resp = await self._http.post(url, headers=headers, data=data, timeout=30.0)
resp.raise_for_status()
payload = resp.json()
return payload["access_token"], payload["expires_in"]
async def _request(self, method: str, path: str, **kwargs) -> dict:
"""Wrapper з auto-token-refresh + retry."""
token = await self._get_access_token()
headers = kwargs.pop("headers", {})
headers.update({
"Authorization": f"Bearer {token}",
"Consumer-Key": self.credentials.consumer_key,
})
url = f"{self._base_url}{path}"
resp = await self._http.request(method, url, headers=headers, **kwargs)
if resp.status_code == 401:
self._token_cache = None # force refresh on next call
raise CarrierAuthError(f"Token expired or invalid for {self.SCAC}")
resp.raise_for_status()
return resp.json()
async def get_quote(self, origin, destination, commodity_code, equipment,
departure_window) -> Sequence[OfferQuote]:
# Maersk Offers API — Maersk-specific, не DCSA
params = {
"origin": origin,
"destination": destination,
"commodity": commodity_code,
"containerType": ",".join(equipment),
"departureFrom": departure_window[0].isoformat(),
"departureTo": departure_window[1].isoformat(),
}
data = await self._request("GET", "/offers/v3/offers", params=params)
return [OfferQuote.from_maersk_offer(o) for o in data.get("offers", [])]
async def create_booking(self, request: BookingRequest) -> BookingConfirmation:
# DCSA Booking 2.0 endpoint
payload = request.model_dump(by_alias=True, exclude_none=True)
data = await self._request("POST", "/booking/v2/bookings", json=payload)
return BookingConfirmation.model_validate(data)
async def submit_vgm(self, submission: VGMSubmission) -> str:
# DCSA VGM v1.0 endpoint (Nov 2025 standard)
payload = submission.model_dump(by_alias=True, exclude_none=True)
data = await self._request(
"POST", "/vgm/v1/verified-gross-mass", json=payload,
)
return data["vgmReference"]
async def stream_events(self, carrier_booking_ref, since=None):
# DCSA TNT v2.2 polling (preferred: webhook subscription)
params = {"carrierBookingReference": carrier_booking_ref}
if since:
params["eventCreatedDateTime[gte]"] = since.isoformat()
data = await self._request("GET", "/track-and-trace/v2/events", params=params)
for event in data.get("events", []):
yield TransportEvent.model_validate(event)
# ... issue_bill_of_lading, get_booking_status — analogous
6.3. AggregatorCarrierAdapter (VizionAdapter example)¶
# backend/shipcore/integrations/vizion/adapter.py
class VizionAdapter(BaseCarrierAdapter):
"""Aggregator-based adapter. Mainly реалізує stream_events для tracking,
quote/booking/BL/VGM не підтримуються — обмеження aggregator scope.
`SCAC` тут — placeholder; реальний carrier_code приходить per shipment."""
SCAC = "VIZN" # synthetic
DCSA_VERSIONS = {"tnt": "2.2"} # only T&T mapped
async def get_quote(self, *args, **kwargs):
raise NotImplementedError("Aggregator does not support quotes")
async def create_booking(self, *args, **kwargs):
raise NotImplementedError("Aggregator does not support bookings")
async def submit_vgm(self, *args, **kwargs):
raise NotImplementedError("Aggregator does not support VGM submission")
async def issue_bill_of_lading(self, *args, **kwargs):
raise NotImplementedError("Aggregator does not support BL issuance")
async def stream_events(self, carrier_booking_ref, since=None):
# Vizion REST + webhooks
...
6.4. Adapter registry & dispatching¶
# backend/shipcore/integrations/registry.py
from shipcore.integrations.maersk import MaerskSpotAdapter
from shipcore.integrations.hapag import HapagLloydAdapter # Phase 8
from shipcore.integrations.cmacgm import CMACGMAdapter # Phase 8
from shipcore.integrations.msc import MSCAdapter # Phase 8
from shipcore.integrations.vizion import VizionAdapter # Phase 5 fallback
DIRECT_ADAPTERS = {
"MAEU": MaerskSpotAdapter,
"HLCU": HapagLloydAdapter,
"CMDU": CMACGMAdapter,
"MSCU": MSCAdapter,
}
def resolve_adapter(carrier_scac: str, credentials_provider) -> BaseCarrierAdapter:
cls = DIRECT_ADAPTERS.get(carrier_scac)
if cls is not None:
creds = credentials_provider.get(carrier_scac)
return cls(credentials=creds)
# Fallback to aggregator
creds = credentials_provider.get("VIZION")
return VizionAdapter(credentials=creds)
Architectural note. Цей паттерн чітко відображає D11 (hybrid direct + aggregator) і D9 (Maersk first). Реєстр — explicit dictionary (не Django entry_points), щоб уникнути magic registration і дозволити type-checking.
7. DCSA OpenAPI v2.0.1 compliance check для кожного adapter¶
⚠️ Важлива знахідка: "v2.0.1" з оригінального завдання — застаріла маркіровка. GitHub repo dcsaorg/DCSA-OpenAPI має release tag 2.0.1 від травня 2021, але це загальна репо-версія, не version individual specs. Поточний state на травень 2026:
| DCSA Standard | Поточна версія | Status | Released |
|---|---|---|---|
| Track & Trace (TNT) | 2.2 | Final ✅ | 2024-Q4 |
| Booking (BKG) | 2.0 (final) | Final ✅ | 2025-02-20 |
| Bill of Lading (EBL) | 3.0 (final) | Final ✅ | 2025-02-20 |
| EBL Issuance (EBL ISS) | 1.0 | Final ✅ | 2024 |
| EBL Surrender (EBL SUR) | 1.0 | Final ✅ | 2024 |
| Operational Vessel Schedules (OVS) | 3.0 | Beta 🟡 | 2024 |
| Commercial Schedules (CS) | 1.0 | Final ✅ | 2024 |
| Just in Time PortCalls (JIT) | 1.2 | Final ✅ | 2023 |
| Platform Interoperability (PINT) | 1.0 | Beta 🟡 | 2024 |
| VGM | 1.0 | Final ✅ | 2025-11-18 |
7.1. Compliance matrix per carrier¶
| Carrier | TNT 2.2 | Booking 2.0 | BL 3.0 | VGM 1.0 | OVS | CS | JIT |
|---|---|---|---|---|---|---|---|
| Maersk | ✅ live | ✅ live | ✅ live | 🟡 expected Q1 2026 | ✅ | ✅ | 🟡 |
| Hapag-Lloyd | ✅ live | 🟡 in progress | 🟡 in progress | 🟡 expected | ✅ | ✅ | 🟡 |
| CMA CGM | ✅ live | 🟡 in progress | 🟡 in progress | 🟡 expected | ✅ | ✅ | 🟡 |
| MSC | 🟡 in progress | 🟡 scheduled | 🟡 scheduled | 🟡 expected | 🟡 | ✅ live | 🟡 |
| ONE / ZIM / COSCO / Evergreen / Yang Ming / HMM | 🟡 founders, varying adoption | ⚠️ unknown | ⚠️ unknown | ⚠️ unknown | ⚠️ | ⚠️ | ⚠️ |
Implication для CarrierAdapter design. Якщо ShipCore генерує pydantic models з DCSA OpenAPI YAML, ми отримуємо single source of truth що працює для всіх direct-adapters. Carrier-specific divergences (наприклад, Maersk Track & Trace Plus extra fields) — модельовані як optional extension fields.
8. Cost analysis: API access / aggregator subscriptions / implementation effort¶
8.1. Per-carrier integration cost (Phase 5 + 8 horizon)¶
| Component | Setup effort | Maintenance/year | API access cost/year |
|---|---|---|---|
| Maersk (Phase 5) | 80-100 hours (включно з sandbox testing) | ~30 hours | $0 (free tier; reserved future paid) |
| Hapag-Lloyd (Phase 8) | 50-70 hours (-30% vs Maersk через DCSA reuse) | ~20 hours | $0 (free tier) |
| CMA CGM (Phase 8) | 50-70 hours; +10 hours для two-tier handling | ~20 hours | Public free 30 днів, потім ~$200-500/міс private 🟡 |
| MSC (Phase 8) | 60-80 hours; +20 hours якщо доводиться EDI fallback | ~25 hours | $0 confirmed (?) |
| Vizion (aggregator) (Phase 5 fallback) | 30-40 hours | ~15 hours | $200-500/міс per ~1000 containers, ~$2.4-6K/year 🟡 |
| Terminal49 (alternative) | 30-40 hours | ~15 hours | Free <100 containers, paid plans custom 🟡 |
| Geotab (Phase 8 EU expansion) | 60-80 hours (poll-based feed pattern) | ~25 hours | Hardware-bundled (~$25-35/vehicle/month) 🟡 |
| Samsara (Phase 8 alternative) | 50-70 hours (REST + webhooks 2.0 cleaner DX) | ~20 hours | Custom quote (~$25-40/vehicle/month estimated) 🟡 |
| Webfleet (Phase 8 alternative) | 70-90 hours (legacy SOAP overhead) | ~30 hours | Customer license required 🟡 |
| Wialon (Phase 5, already integrated) | already done | ~10 hours | Hosting subscription ($1-3/object/month) 🟡 |
8.2. Total Phase 5 (Maersk + Vizion) cost estimate¶
Setup (one-time):
Maersk adapter: 80-100 hours
Vizion adapter: 30-40 hours
CarrierAdapter base: 40-60 hours (reusable infra)
DCSA pydantic models gen: 20-30 hours (one-time setup, reused)
Integration tests: 40-60 hours
TOTAL setup: ~210-290 hours = ~5-7 weeks of 1 dev FTE ✅
(matches Phase 5 estimate from roadmap)
Year 1 operating:
Vizion subscription: ~$3K (1K containers/month)
Maersk: $0
Maintenance: ~45 hours
TOTAL Year 1 OPEX: ~$3K + 45 hours dev time
8.3. WIN platform — buy decision threshold¶
Build alternative (Phase 7 internal LaneRateHistory + DCSA Schedules):
Estimated effort: 2-3 weeks dev (~80-120 hours)
Maintenance: ~30 hours/year
Cost: $0 external
WIN partnership:
Setup: ~40-60 hours (per Web Service API docs)
Subscription: UNKNOWN (estimated $200-500/month per forwarder seat 🟡)
Year 1: ~$2.4-6K + 60 hours
Decision rule:
IF (WIN_year1_cost / 3) < (build_cost - WIN_setup_cost)
AND (WIN delivers air carrier coverage we cannot build cost-effectively)
THEN buy (subscribe to WIN)
ELSE build (LaneRateHistory + DCSA Schedules + manual carrier outreach)
Recommendation: Phase 7 = 2-3 days research включно з outreach call (service@winwebconnect.com). Якщо Year-1 cost <$3K і покриває 50+ EU carriers air+ocean → buy. Якщо >$10K/year або mostly air-only → build.
9. Recommended implementation order для Phase 5/8/9+¶
Phase 5 (Sea P0 — Maersk Spot first)¶
Тиждень 1-2: Foundation
1. ✅ Create backend/shipcore/integrations/ package skeleton
2. ✅ Generate pydantic v2 models з DCSA OpenAPI YAML (TNT 2.2, Booking 2.0, BL 3.0, VGM 1.0) — single source of truth
3. ✅ Implement BaseCarrierAdapter ABC + CarrierCredentials data class
4. ✅ Implement httpx.AsyncClient factory with retry/backoff middleware
5. ✅ Setup TenantSecret encrypted storage для carrier credentials per tenant
Тиждень 3-4: MaerskSpotAdapter
6. ✅ Implement OAuth2 token caching (_refresh_token, _get_access_token)
7. ✅ Implement get_quote (Maersk Offers API)
8. ✅ Implement create_booking (DCSA Booking 2.0)
9. ✅ Implement stream_events (DCSA TNT 2.2 polling) + webhook subscription
10. ✅ Implement submit_vgm (DCSA VGM 1.0)
11. ✅ Implement issue_bill_of_lading (DCSA BL 3.0)
12. ✅ Sandbox integration tests (port-pairs USCHI-DEHAM + CNSHA-USLAX)
Тиждень 5: Vizion fallback + dispatch
13. ✅ Implement VizionAdapter (tracking-only)
14. ✅ Implement resolve_adapter registry function
15. ✅ Wire shipcore_forwarder.Booking workflow to use adapter via SCAC dispatch
Тиждень 6 (buffer): pilot integration 16. ✅ Pilot with Wave 1 UA road carrier (sandbox-only якщо немає Maersk contract) 17. ✅ Bug fixes + observability (logging, metrics, alerting)
Phase 5.5 (1-2 тижні NEW — Дунайські TOS, per C1)¶
Поза scope цього document — TOS specific, не carrier API.
Phase 7 (Pricing + WIN research)¶
Тиждень 1: WIN research
1. ✅ Outreach до service@winwebconnect.com для pricing quote
2. ✅ Read WIN Air Freight API PDF docs (winwebconnect.com/Public/Resources/TechDocs/WIN%20Air%20Freight%20API.pdf)
3. ✅ Scope assessment: air-only, ocean coverage, DCSA-aligned?
4. ✅ buy-vs-build decision per § 8.3 threshold
Тиждень 2-3: Implementation
5. ✅ Якщо WIN buy: implement WINAdapter (similar pattern, SOAP/REST)
6. ✅ Якщо build: extend shipcore_pricing.LaneRateHistory to scrape DCSA Commercial Schedules + carrier OPEX models
Phase 8 (Sea P1 + EU expansion + EU telematics)¶
Sequence (parallel where possible):
- Hapag-Lloyd adapter (~50-70 hours) — найшвидший win завдяки cleanest dev portal
- CMA CGM adapter (~60-80 hours) — two-tier complexity але public tier перевага для discovery
- MSC adapter (~60-80 hours) — починаємо з Schedules + T&T, Booking 2.0 коли live
- eBL interop hubs (~80-120 hours) — CargoX, WaveBL, Enigio, TradeGo, IQAX-GSBN (per C6)
- Geotab OR Samsara (vendor selection 1 day, integration 50-80 hours)
- DigiCMR / TransFollow / Open Logistics Foundation eCMR (per C-eFTI-byDesign)
- EU sanctions screening (free EU XML feed integration, ~30-40 hours)
- ICS2 pre-arrival declarations (per C7 — критично для UA→EU транзитів)
Phase 9+ (Air via Awery + remaining sea)¶
Sequence:
- Awery partnership outreach (during Phase 4-5 window per C2 — раніше initiated, не пізніше)
- AweryAdapter via ONE Record (Awery developing open-source PHP ONE Record server — можемо переюзати їхню schema models)
- ONE / ZIM / COSCO / Evergreen / Yang Ming / HMM via Vizion (no direct adapters until volume justifies)
Summary table — Carrier APIs by phase¶
| Phase | Component | Effort | DCSA-aligned | Cost Year 1 |
|---|---|---|---|---|
| 5 | Maersk Spot direct | 80-100h | ✅ Booking 2.0, TNT 2.2, BL 3.0, VGM 1.0 | $0 |
| 5 | Vizion fallback | 30-40h | aggregator | ~$3K/year |
| 5 | Wialon (existing) | done | n/a (vendor proprietary) | hosting |
| 5.5 | Дунайські TOS (per C1) | 1-2 weeks | n/a (own TOS) | $0 |
| 7 | WIN research → buy/build | 2-3 days research + 2-3 weeks impl | depends | $0-6K/year |
| 8 | Hapag-Lloyd direct | 50-70h | ✅ TNT 2.2; Booking 2.0 in progress | $0 |
| 8 | CMA CGM direct | 60-80h | ✅ TNT 2.2; CS 1.0; BKG/BL in progress | ~$3-6K/year private tier |
| 8 | MSC direct | 60-80h | 🟡 CS 1.0 live; BKG/eBL scheduled | $0 |
| 8 | eBL interop (CargoX/WaveBL/Enigio/TradeGo/IQAX) | 80-120h | DCSA EBL 3.0 ✅ | ~$2-5K/year hub |
| 8 | Geotab OR Samsara EU telematics | 50-80h | n/a | ~$25-40/vehicle/month |
| 9+ | Awery API (air) | 60-80h post-partnership | ONE Record ✅ | partnership-dependent |
| 9+ | Vizion-only carriers (ONE/ZIM/COSCO/Evergreen/YML/HMM) | 0h (already covered) | DCSA TNT via aggregator | included in Vizion subscription |
Open questions deferred до Phase 3+¶
- Maersk rate limits — exact numbers. Не публічно. Action: при отриманні sandbox credentials — тестувати empirically (e.g., burst 100 RPS until 429), документувати у adapter docstring.
- MSC OAuth2 specifics. Не verified публічно. Action: Phase 8 — read MSC developer portal docs after registration.
- Hapag-Lloyd Booking 2.0 / BL 3.0 timelines. Public roadmap absent. Action: Phase 8 — direct outreach to Hapag API team.
- WIN actual subscription pricing. Не на сайті. Action: Phase 7 outreach call.
- Geotab vs Samsara final selection. ABI Research → Geotab. Capterra UX → Samsara. Action: Phase 8 — pilot trial both for 30 days, decide based on UA hardware availability + EU support presence.
- DCSA OpenAPI Python codegen tooling.
datamodel-code-generator(Python) vsopenapi-python-clientvs custom. Action: Phase 4 prototype, document in adapter README. - Awery commercial partnership terms. Action: outreach під час Phase 4-5 calendar window (per C2) — earliest possible, бо partnership negotiations типово 3-6 months.
Phase 2 carrier APIs deep-dive закрито 2026-05-12. Phase 3 (data model deep-dive — DCSA pydantic generation, Waybill canonical projections, multi-leg execution) стартує з цих припущень.
Sources¶
DCSA standards¶
- DCSA Booking standards documentation
- DCSA Booking 2.0 final + BL 3.0 final release
- DCSA Track & Trace v2.2 release
- DCSA TNT v2.2.0 OpenAPI YAML on GitHub
- DCSA-OpenAPI repo
- DCSA VGM standard documentation
- DCSA publishes API standard for verified container weights (Smart Maritime Network, Nov 2025)
- DCSA launches API Standard for VGM (Container News)
- DCSA API Portal
- Top carriers adopting DCSA track and trace standards (Splash247)
Maersk¶
- Maersk Developer Portal — API Catalogue
- Maersk Offers API documentation
- Maersk Offers API endpoints overview
- Maersk Ocean Booking v2 [DCSA]
- Maersk Ocean Booking Status Webhook [DCSA]
- Maersk DCSA Bill of Lading
- Maersk Track and Trace Plus
- Maersk OAuth 2.0 authorisation guide
- Maersk Getting Started API
- Maersk Onboarding Guide (sandbox)
- Maersk pricing FAQ
- Maersk Data Integrations EDI & API
Hapag-Lloyd¶
- Hapag-Lloyd API Portal
- Hapag-Lloyd API Developer Portal docs
- Hapag-Lloyd Getting Started
- Hapag-Lloyd Quotation/Booking Engine API
- Hapag-Lloyd Quick Quotes
- Hapag-Lloyd Quick Quotes Spot
- Hapag-Lloyd DCSA Track & Trace via Youredi CCL
- Dachser-Descartes-Hapag Spot Rates integration
CMA CGM¶
- CMA CGM API Portal
- CMA CGM API Starting Guide
- CMA CGM EDI & API Solutions
- CMA CGM API Catalog
- CMA CGM API Pricing
- CMA CGM DCSA Track & Trace v2.2.0 product
MSC¶
- MSC EDI and API Shipment Management
- MSC Developer Portal API Catalogue
- MSC adopts DCSA API for standardised schedule data exchange (Smart Maritime Network)
- MSC blog on DCSA Commercial Schedules adoption
Vizion / Terminal49¶
- Vizion API homepage
- Vizion API features
- Vizion API pricing
- Vizion API overview
- Vizion pricing comparison (Tradlinx)
- Terminal49 homepage
- Terminal49 Container Tracking API
- Terminal49 API pricing plans
- Terminal49 Shipping Lines coverage
- Terminal49 API Data Sources and Availability
Road telematics¶
- Geotab Developers home
- MyGeotab API Reference
- Geotab Data Feed guide
- Geotab Better practices
- MyGeotab API Adapter
- Samsara Developers REST API Overview
- Samsara Webhooks docs
- Samsara Quickstart
- Samsara Python SDK
- Webfleet Developer Resources
- WEBFLEET.connect API documentation
- Bridgestone-TomTom Webfleet partnership
- ABI Research telematics ranking (Geotab #1)
Wialon¶
WIN platform¶
- WIN web home (Winweb Connect)
- WIN Airfreight product page
- WIN Airfreight Airlines Network
- WIN Air Freight API PDF (Release 3.5)
- WIN API Reference
- Riege implements WIN platform into Scope
- Riege Scope freight forwarding software
- Riege Scope ocean freight
Awery + ONE Record¶
- Awery Aviation Software homepage
- Awery wins fifth IATA ONE Record Hackathon (CargoForwarder Global, May 2026)
- Awery wins fifth IATA ONE Record Hackathon (Air Cargo News)
- Awery wins 4th hackathon with open-source ONE Record server (Air Cargo Week)
- IATA ONE Record fact sheet (December 2025)
- IATA ONE Record program
- IATA Cargo-XML Standards (containment 2026-01)
- IATA ONE Record GitHub repo
- IATA ONE Record 2026 industry analysis (Impactograph)
- Open Logistics Foundation NE:ONE