openapi: 3.0.3 info: title: Carrier Schedule Query API version: 1.0.0 description: Six-carrier query tasks with a three-day window, at most three attempts, and explicit manual fallback. paths: /api/platform/v1/carrier-schedule-queries/carriers: get: summary: List official carrier sources and compliant access modes responses: '200': {description: MATSON, SML, ZIM, COSCO, EMC and HEDE descriptors} /api/platform/v1/carrier-schedule-queries: get: summary: Query carrier schedule tasks parameters: - {name: customerId, in: query, schema: {type: integer, format: int64, minimum: 1}} - {name: oceanBookingId, in: query, schema: {type: integer, format: int64, minimum: 1}} - {name: containerBookingId, in: query, schema: {type: integer, format: int64, minimum: 1}} - {name: carrierCode, in: query, schema: {$ref: '#/components/schemas/CarrierCode'}} - {name: status, in: query, schema: {$ref: '#/components/schemas/QueryStatus'}} - {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: Query tasks with source, freshness and rate-limit fields} post: summary: Create a query task linked to a real booking and allocated container parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/CreateRequest'} responses: '200': {description: Created task or idempotent replay} /api/platform/v1/carrier-schedule-queries/{queryId}: parameters: [{$ref: '#/components/parameters/QueryId'}] get: summary: Get task, immutable attempts and history responses: '200': {description: Stable task detail} /api/platform/v1/carrier-schedule-queries/{queryId}/history: parameters: [{$ref: '#/components/parameters/QueryId'}] get: summary: Get immutable task history responses: '200': {description: CREATE, ATTEMPT and MANUAL_RESULT history} /api/platform/v1/carrier-schedule-queries/{queryId}/attempts: parameters: [{$ref: '#/components/parameters/QueryId'}] post: summary: Execute the compliant carrier strategy; never bypass captcha or dynamic pages parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/AttemptRequest'} responses: '200': {description: MANUAL_REQUIRED with coverageGap when no public structured API is available} /api/platform/v1/carrier-schedule-queries/{queryId}/manual-results: parameters: [{$ref: '#/components/parameters/QueryId'}] post: summary: Link a validated manual port-schedule observation without pretending automated success parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/ManualResultRequest'} responses: '200': {description: Successful manual fallback and next query time} components: parameters: QueryId: {name: queryId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}} IdempotencyKey: {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 1, maxLength: 128}} schemas: CarrierCode: {type: string, enum: [MATSON, SML, ZIM, COSCO, EMC, HEDE]} TrackingType: {type: string, enum: [BOOKING_NO, BILL_OF_LADING, CONTAINER_NO]} QueryStatus: {type: string, enum: [READY, MANUAL_REQUIRED, SUCCESS]} CreateRequest: type: object required: [expectedVersion, customerId, oceanBookingId, carrierCode, trackingType, trackingNo] properties: expectedVersion: {type: integer, minimum: 0, maximum: 0} customerId: {type: integer, format: int64, minimum: 1} oceanBookingId: {type: integer, format: int64, minimum: 1} containerBookingId: {type: integer, format: int64, minimum: 1, nullable: true} carrierCode: {$ref: '#/components/schemas/CarrierCode'} trackingType: {$ref: '#/components/schemas/TrackingType'} trackingNo: {type: string, minLength: 1, maxLength: 128} remark: {type: string, nullable: true, maxLength: 1000} AttemptRequest: type: object required: [expectedVersion] properties: expectedVersion: {type: integer, minimum: 0} reason: {type: string, nullable: true, maxLength: 1000} ManualResultRequest: type: object required: [expectedVersion, portScheduleId, reason] properties: expectedVersion: {type: integer, minimum: 0} portScheduleId: {type: integer, format: int64, minimum: 1} reason: {type: string, minLength: 1, maxLength: 1000} QueryView: type: object required: [query, expired, maxAttempts, nextAllowedAt] properties: query: {type: object, description: Includes source, attemptCount, lastAttemptAt, lastSuccessAt, sourceUpdatedAt and manualReason} expired: {type: boolean} maxAttempts: {type: integer, enum: [3]} nextAllowedAt: {type: string, format: date-time}