openapi: 3.0.3 info: title: Phase 3 Customs Collaboration API version: 1.0.0 description: Immutable checklist and file versions, supplement requests, frozen agent batches, receipts and history. paths: /api/platform/v1/customs/checklist-versions: post: summary: Create an immutable customs document checklist version parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] responses: {'200': {description: Checklist version}} /api/platform/v1/customs/cases: get: summary: Page customs cases responses: {'200': {description: Page result}} post: summary: Create a customer/order/inbound/container scoped customs case parameters: [{$ref: '#/components/parameters/IdempotencyKey'}] responses: {'200': {description: Customs case detail}} /api/platform/v1/customs/cases/{caseId}: parameters: [{$ref: '#/components/parameters/CaseId'}] get: summary: Query complete customs detail and stable history responses: {'200': {description: Detail}} /api/platform/v1/customs/cases/{caseId}/documents: parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}] post: summary: Reference a file validated against customer, CUSTOMS_DOCUMENT and case ID responses: {'200': {description: New document version}} /api/platform/v1/customs/cases/{caseId}/documents/upload: parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}] post: summary: Upload a document and create a new immutable version requestBody: required: true content: multipart/form-data: schema: type: object required: [itemCode, expectedVersion, file] properties: itemCode: {type: string} expectedVersion: {type: integer, minimum: 0} file: {type: string, format: binary} responses: {'200': {description: New document version}} /api/platform/v1/customs/cases/{caseId}/documents/{documentId}/review: parameters: - {$ref: '#/components/parameters/CaseId'} - {name: documentId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}} - {$ref: '#/components/parameters/IdempotencyKey'} post: summary: Approve a current file version or return it with a supplement task responses: {'200': {description: Updated detail}} /api/platform/v1/customs/cases/{caseId}/submission-batches: parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}] post: summary: Submit to customs agent and freeze approved file versions in a batch snapshot description: customsAgentId must identify an ACTIVE Warehouse supplier in category CUSTOMS; the persisted agent name is resolved server-side and free text cannot bypass supplier validation. requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/SubmitBatchRequest'}}}} responses: '200': description: Submission batch content: application/json: schema: {$ref: '#/components/schemas/CustomsSubmissionBatch'} /api/platform/v1/customs/submission-batches/{batchId}/receipts: parameters: - {name: batchId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}} - {$ref: '#/components/parameters/IdempotencyKey'} post: summary: Reference a customer-owned receipt file with explicit visibility responses: {'200': {description: Receipt version}} /api/platform/v1/customs/submission-batches/{batchId}/receipts/upload: post: summary: Upload a receipt version; RELEASED closes the customs dispatch gate responses: {'200': {description: Receipt version}} /api/merchant/v1/customs/orders/{orderId}: get: summary: Query the authenticated customer's customs case by order responses: {'200': {description: Customer-filtered detail}} /api/merchant/v1/customs/cases/{caseId}/documents/upload: post: summary: Upload or replace a checklist document within authenticated customer scope responses: {'200': {description: New document version}} /api/merchant/v1/customs/cases/{caseId}/receipts/{receiptId}/download: get: summary: Download only CUSTOMER-visible receipts from the authenticated customer's case responses: {'200': {description: Authorized file stream}} components: parameters: IdempotencyKey: name: Idempotency-Key in: header required: true schema: {type: string, minLength: 1, maxLength: 128} CaseId: name: caseId in: path required: true schema: {type: string, pattern: '^[1-9][0-9]*$'} schemas: SubmitBatchRequest: type: object required: [customsAgentId, expectedVersion] properties: customsAgentId: {type: integer, format: int64, minimum: 1, description: ACTIVE Warehouse supplier ID validated as CUSTOMS.} customsAgentName: {type: string, maxLength: 128, nullable: true, description: Optional consistency hint; persisted name always comes from Warehouse.} externalReference: {type: string, maxLength: 128, nullable: true} note: {type: string, maxLength: 500, nullable: true} expectedVersion: {type: integer, minimum: 0} CustomsSubmissionBatch: type: object required: [id, customsCaseId, batchNo, batchVersion, customsAgentName, status, submittedBy, submittedAt] properties: id: {type: string, pattern: '^[1-9][0-9]*$'} customsCaseId: {type: string, pattern: '^[1-9][0-9]*$'} batchNo: {type: string, maxLength: 40} batchVersion: {type: integer, minimum: 1} customsAgentId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: Server-validated CUSTOMS supplier ID snapshot; null only for non-migrated historical rows.} customsAgentName: {type: string, maxLength: 128, description: Server-frozen Warehouse supplier name snapshot.} externalReference: {type: string, maxLength: 128, nullable: true} fileSnapshotJson: {type: string} status: {type: string, enum: [SUBMITTED, ACKNOWLEDGED, REJECTED, COMPLETED]} note: {type: string, maxLength: 500, nullable: true} submittedBy: {type: string, pattern: '^[1-9][0-9]*$'} submittedByName: {type: string, maxLength: 64, nullable: true} submittedAt: {type: string, format: date-time}