openapi: 3.0.3 info: {title: Phase 3 Ocean Booking API, version: 1.1.0} paths: /api/platform/v1/ocean-bookings/channels: get: summary: List logistics channels from the current ACTIVE price book for an origin warehouse description: 'Requires platform:firstleg:ocean-booking:list. Returns only channels with an ACTIVE price row; the selected channel name is frozen server-side on draft save.' parameters: - {name: originWarehouseId, in: query, required: true, schema: {type: integer, format: int64, minimum: 1}} responses: {'200': {description: Available channel options, content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/ChannelOption'}}}}}} /api/platform/v1/ocean-bookings: post: summary: Create an ocean booking draft with immutable channel and warehouse snapshots parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/CreateRequest'}}}} responses: {'200': {description: Draft detail}} /api/platform/v1/ocean-bookings/{oceanBookingId}/confirm: post: summary: Confirm booking and atomically create one stable cabinet and editing loading plan per requested quantity parameters: [{$ref: '#/components/parameters/OceanBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ActionRequest'}}}} responses: {'200': {description: CONFIRMED detail; no real container number required}} /api/platform/v1/ocean-bookings/{oceanBookingId}/release: post: summary: Confirm released transport data and synchronize associated cabinet transport snapshots description: Does not create cabinets, change channels, replace cabinetNo, or recreate loading plans. 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}} 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: CreateRequest: type: object required: [expectedVersion, data] properties: expectedVersion: {type: integer, enum: [0]} data: {$ref: '#/components/schemas/DraftData'} DraftData: type: object required: [customerId, customerName, channelCode, warehouseId, warehouseName, parties, containerRequirements] properties: customerId: {type: integer, format: int64, minimum: 1} customerName: {type: string, maxLength: 128} channelCode: {type: string, maxLength: 64, description: Selected from GET /api/platform/v1/ocean-bookings/channels; server validates it against the current ACTIVE price book and freezes channelName.} warehouseId: {type: integer, format: int64, minimum: 1} warehouseName: {type: string, maxLength: 128} billOfLadingNo: {type: string, nullable: true, deprecated: true, description: Must be omitted until release} vesselName: {type: string, nullable: true, deprecated: true, description: Must be omitted until release} voyageNo: {type: string, nullable: true, deprecated: true, description: Must be omitted until release} estimatedSailingAt: {type: string, format: date-time, nullable: true, deprecated: true, description: Must be omitted until release} estimatedArrivalAt: {type: string, format: date-time, nullable: true, deprecated: true, description: Must be omitted until release} parties: {type: array, minItems: 3, items: {type: object}} containerRequirements: {type: array, minItems: 1, maxItems: 20, items: {$ref: '#/components/schemas/ContainerRequirement'}} ContainerRequirement: type: object required: [containerType, containerKind, capacityCbm, maxWeightKg, quantity] properties: containerType: {type: string, maxLength: 32} containerKind: {type: string, maxLength: 32} capacityCbm: {type: number, exclusiveMinimum: true, minimum: 0} maxWeightKg: {type: number, exclusiveMinimum: true, minimum: 0} quantity: {type: integer, minimum: 1} ChannelOption: type: object required: [priceBookVersionId, channelCode, channelName, priceModel, pricingTaxModes] properties: priceBookVersionId: {type: integer, format: int64} channelCode: {type: string, maxLength: 64} channelName: {type: string, maxLength: 128} priceModel: {type: string} pricingTaxModes: {type: array, items: {type: string}} ActionRequest: type: object required: [expectedVersion] properties: {expectedVersion: {type: integer, minimum: 0}, reason: {type: string, maxLength: 1000}} ReleaseRequest: type: object required: [expectedVersion, billOfLadingNo, vesselName, voyageNo, estimatedSailingAt, estimatedArrivalAt] properties: expectedVersion: {type: integer, minimum: 0} billOfLadingNo: {type: string, maxLength: 128} vesselName: {type: string, maxLength: 128} voyageNo: {type: string, maxLength: 64} estimatedSailingAt: {type: string, format: date-time} estimatedArrivalAt: {type: string, format: date-time} reason: {type: string, maxLength: 1000}