2026-08-12 17:29:30 +08:00
openapi : 3.0.3
2026-08-18 15:43:58 +08:00
info : {title : Ocean Booking API, version : 2.0.0 }
2026-08-12 17:29:30 +08:00
paths :
/api/platform/v1/ocean-bookings :
2026-08-18 15:43:58 +08:00
get : {summary : List DRAFT and RELEASED bookings, responses : {'200' : {description : Booking page}}}
2026-08-12 17:29:30 +08:00
post :
2026-08-18 15:43:58 +08:00
summary : Create an editable DRAFT
description : Creates only the booking aggregate and container requirements; no containerNo, container row, or allocation is created.
2026-08-12 17:29:30 +08:00
parameters : [ {$ref : '#/components/parameters/IdempotencyKey' }]
requestBody : {required : true, content : {application/json : {schema : {$ref : '#/components/schemas/CreateRequest' }}}}
2026-08-18 15:43:58 +08:00
responses : {'200' : {description : DRAFT detail}}
/api/platform/v1/ocean-bookings/{oceanBookingId}:
get : {summary : Get booking detail, parameters : [ {$ref : '#/components/parameters/OceanBookingId' }], responses : {'200' : {description : Detail}}}
put :
summary : Replace a DRAFT
parameters : [ {$ref : '#/components/parameters/OceanBookingId' }, {$ref : '#/components/parameters/IdempotencyKey' }]
requestBody : {required : true, content : {application/json : {schema : {$ref : '#/components/schemas/UpdateRequest' }}}}
responses : {'200' : {description : Updated DRAFT}}
delete :
summary : Delete a DRAFT; RELEASED is immutable
parameters : [ {$ref : '#/components/parameters/OceanBookingId' }, {$ref : '#/components/parameters/IdempotencyKey' }]
requestBody : {required : true, content : {application/json : {schema : {$ref : '#/components/schemas/ActionRequest' }}}}
responses : {'200' : {description : Deleted}}
2026-08-12 17:29:30 +08:00
/api/platform/v1/ocean-bookings/{oceanBookingId}/release:
post :
2026-08-18 15:43:58 +08:00
summary : Validate and permanently release a DRAFT
description : Release validates the persisted aggregate and never requires or creates a real container number.
2026-08-12 17:29:30 +08:00
parameters : [ {$ref : '#/components/parameters/OceanBookingId' }, {$ref : '#/components/parameters/IdempotencyKey' }]
requestBody : {required : true, content : {application/json : {schema : {$ref : '#/components/schemas/ReleaseRequest' }}}}
responses : {'200' : {description : RELEASED detail}}
2026-08-18 15:43:58 +08:00
/api/platform/v1/ocean-bookings/channels :
2026-08-18 16:39:39 +08:00
get :
summary : List ACTIVE channels for an origin warehouse
description : Requires platform:firstleg:ocean-booking:list. Channel names are resolved from the current ACTIVE price book and frozen by the server on save.
parameters :
- {name : originWarehouseId, in : query, required : true, schema : {type : integer, format : int64, minimum : 1 }}
responses :
'200' :
description : Channel options
content :
application/json :
schema : {type : array, items : {$ref : '#/components/schemas/ChannelOption' }}
2026-08-12 17:29:30 +08:00
components :
parameters :
OceanBookingId : {name : oceanBookingId, in : path, required : true, schema : {type : integer, format : int64, minimum : 1 }}
IdempotencyKey : {name : Idempotency-Key, in : header, required : true, schema : {type : string, maxLength : 128 }}
schemas :
2026-08-18 15:43:58 +08:00
CreateRequest : {type : object, required : [expectedVersion, data], properties : {expectedVersion : {type : integer, enum : [0]}, data : {$ref : '#/components/schemas/DraftData' }}}
UpdateRequest : {type : object, required : [expectedVersion, data], properties : {expectedVersion : {type : integer, minimum : 0}, data : {$ref : '#/components/schemas/DraftData' }}}
DraftData :
2026-08-17 19:51:54 +08:00
type : object
2026-08-18 15:43:58 +08:00
description : Fields may be incomplete in DRAFT. RELEASE validates the complete persisted aggregate.
2026-08-17 19:51:54 +08:00
properties :
customerId : {type : integer, format : int64, nullable : true }
customerName : {type : string, nullable : true }
2026-08-18 15:43:58 +08:00
channelCode : {type : string, nullable : true }
warehouseId : {type : integer, format : int64, nullable : true }
billOfLadingNo : {type : string, nullable : true }
2026-08-17 19:51:54 +08:00
shippingCompanyId : {type : integer, format : int64, nullable : true }
shippingCompanyName : {type : string, nullable : true }
2026-08-18 16:39:39 +08:00
bookingAgentId :
type : integer
format : int64
nullable : true
description : Warehouse supplier ID; release validates ACTIVE category BOOKING; booking suppliers do not use domestic/international scope.
bookingAgentName :
type : string
nullable : true
description : Read-only consistency hint; the persisted snapshot always comes from Warehouse.
2026-08-18 15:43:58 +08:00
vesselName : {type : string, nullable : true }
voyageNo : {type : string, nullable : true }
2026-08-17 19:51:54 +08:00
departurePortCode : {type : string, nullable : true }
departurePortName : {type : string, nullable : true }
destinationPortCode : {type : string, nullable : true }
destinationPortName : {type : string, nullable : true }
2026-08-18 15:43:58 +08:00
placeOfDelivery : {type : string, nullable : true }
serviceTerm : {type : string, nullable : true }
freightTerm : {type : string, nullable : true }
2026-08-17 13:24:48 +08:00
estimatedSailingAt : {type : string, format : date-time, nullable : true }
estimatedArrivalAt : {type : string, format : date-time, nullable : true }
2026-08-18 15:43:58 +08:00
remark : {type : string, nullable : true }
parties : {type : array, nullable : true, items : {$ref : '#/components/schemas/PartyRequest' }}
containerRequirements : {type : array, nullable : true, items : {$ref : '#/components/schemas/ContainerRequirementRequest' }}
PartyRequest : {type : object, required : [partyType, partyName], properties : {partyType : {type : string, enum : [SHIPPER, CONSIGNEE, NOTIFY_PARTY]}, partyName : {type : string}, address : {type : string, nullable : true}, contactName : {type : string, nullable : true}, contactPhone : {type : string, nullable : true }}}
ContainerRequirementRequest : {type : object, required : [containerType, containerKind, quantity, capacityCbm, maxWeightKg], properties : {containerType : {type : string}, containerKind : {type : string}, quantity : {type : integer, minimum : 1}, capacityCbm : {type : number, exclusiveMinimum : true, minimum : 0}, maxWeightKg : {type : number, exclusiveMinimum : true, minimum : 0 }}}
ReleaseRequest : {type : object, required : [expectedVersion], properties : {expectedVersion : {type : integer, minimum : 0}, reason : {type : string, nullable : true }}}
ActionRequest : {type : object, required : [expectedVersion], properties : {expectedVersion : {type : integer, minimum : 0}, reason : {type : string, nullable : true }}}
2026-08-18 16:39:39 +08:00
ChannelOption :
type : object
required : [ priceBookVersionId, channelCode, channelName, priceModel, pricingTaxModes]
properties :
priceBookVersionId : {type : integer, format : int64}
channelCode : {type : string}
channelName : {type : string}
priceModel : {type : string}
pricingTaxModes : {type : array, items : {type : string}}
2026-08-18 15:43:58 +08:00
Detail : {type : object, required : [oceanBooking, parties, containerRequirements, containers, histories], properties : {oceanBooking : {type : object}, parties : {type : array}, containerRequirements : {type : array}, containers : {type : array, description : Existing containers allocated after port pickup linking}, histories : {type : array}}}