openapi: 3.0.3 info: title: Platform Port Schedule API version: 1.0.0 description: Independent port and vessel schedule observations linked to ocean bookings and allocated containers. paths: /api/platform/v1/port-schedules: get: summary: Query schedules by customer, ocean booking, allocated container or expiry parameters: - {name: customerId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}} - {name: oceanBookingId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}} - {name: containerBookingId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}} - {name: expired, in: query, schema: {type: boolean}} - {name: keyword, in: query, schema: {type: string, maxLength: 128}} - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}} - {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}} responses: '200': description: HTTP 200 business envelope containing a page of schedule views post: summary: Create a source observation linked to a real ocean booking parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/CreateRequest'} responses: '200': {description: Created detail in the standard business envelope} /api/platform/v1/port-schedules/{portScheduleId}: parameters: [{$ref: '#/components/parameters/PortScheduleId'}] get: summary: Get schedule and immutable history responses: '200': {description: Schedule detail with computed expired flag} put: summary: Update source observation with optimistic locking parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/UpdateRequest'} responses: '200': {description: Updated detail or A0409 conflict in the business envelope} /api/platform/v1/port-schedules/{portScheduleId}/history: parameters: [{$ref: '#/components/parameters/PortScheduleId'}] get: summary: Query immutable source observation history responses: '200': {description: Ordered CREATE and UPDATE history records} components: parameters: PortScheduleId: name: portScheduleId in: path required: true schema: {type: string, pattern: '^[1-9][0-9]*$'} IdempotencyKey: name: Idempotency-Key in: header required: true schema: {type: string, minLength: 1, maxLength: 128} schemas: ScheduleData: type: object required: - customerId - oceanBookingId - sourceType - sourceName - sourceRef - vesselName - voyageNo - departurePortCode - destinationPortCode - observedAt - expiresAt properties: customerId: {type: string, pattern: '^[1-9][0-9]*$'} oceanBookingId: {type: string, pattern: '^[1-9][0-9]*$'} containerBookingId: {type: string, nullable: true, pattern: '^[1-9][0-9]*$'} sourceType: {type: string, enum: [MANUAL, CARRIER, TERMINAL, API]} sourceName: {type: string, maxLength: 128} sourceRef: {type: string, maxLength: 255} vesselName: {type: string, maxLength: 128} voyageNo: {type: string, maxLength: 64} departurePortCode: {type: string, maxLength: 32} departurePortName: {type: string, nullable: true, maxLength: 128} destinationPortCode: {type: string, maxLength: 32} destinationPortName: {type: string, nullable: true, maxLength: 128} etdAt: {type: string, format: date-time, nullable: true} etaAt: {type: string, format: date-time, nullable: true} bookingCutoffAt: {type: string, format: date-time, nullable: true, description: Booking cutoff} customsCutoffAt: {type: string, format: date-time, nullable: true, description: Customs cutoff} portCutoffAt: {type: string, format: date-time, nullable: true, description: Port gate cutoff} observedAt: {type: string, format: date-time} expiresAt: {type: string, format: date-time} remark: {type: string, nullable: true, maxLength: 1000} CreateRequest: type: object required: [expectedVersion, data] properties: expectedVersion: {type: integer, minimum: 0, maximum: 0} data: {$ref: '#/components/schemas/ScheduleData'} reason: {type: string, nullable: true, maxLength: 1000} UpdateRequest: type: object required: [expectedVersion, data] properties: expectedVersion: {type: integer, minimum: 0} data: {$ref: '#/components/schemas/ScheduleData'} reason: {type: string, nullable: true, maxLength: 1000}