{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"title": "Opter transport booking schema",
	"type": "object",
	"additionalProperties": false,
	"properties": {
		"schema": {
			"type": "string",
			"maxLength": 2048,
			"description": "URL or identifier of the schema being used."
		},
		"version": {
			"type": "string",
			"maxLength": 10,
			"description": "Version of the schema."
		},
		"eventCreatedDateTime": {
			"type": "string",
			"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
			"description": "Date and time when the event was created in local time, formatted as 'YYYY-MM-DDTHH:MM:SS'."
		},
		"eventSender": {
			"type": "string",
			"maxLength": 50,
			"description": "Identifier of the message sender. Can usually be generated by the counterpart."
		},
		"eventReceiver": {
			"type": "string",
			"maxLength": 50,
			"description": "Identifier of the message receiver. Can usually be generated by the counterpart."
		},
		"order": {
			"type": "object",
			"additionalProperties": false,
			"description": "Details for price request, creating/updating/revoking orders. *MappingCode is created by Opter EDI team to map a code to be used. *CustomerCode is a code at the transporter that does not need mapping.",
			"properties": {
				"messageType": {
					"type": "string",
					"enum": [
						"new",
						"update",
						"pricerequest",
						"revoke"
					],
					"description": "Defines the type of message: create a new order, update, revoke or request price."
				},
				"customerOrderReference": {
					"type": "string",
					"maxLength": 50,
					"description": "Order reference from the customer. Often the same as freight bill number."
				},
				"opterOrderId": {
					"type": "number",
					"description": "Unique Opter identifier for an order, if needed."
				},
				"payingCustomerCode": {
					"type": "string",
					"maxLength": 50,
					"description": "Code or number for the transport paying customer."
				},
				"serviceMappingCode": {
					"type": "string",
					"maxLength": 50,
					"description": "Mapped service code."
				},
				"vehicleMappingCode": {
					"type": "string",
					"maxLength": 50,
					"description": "Mapped vehicle code."
				},
				"freightBillNumber": {
					"type": "string",
					"maxLength": 50,
					"description": "Freight bill number."
				},
				"customerProject": {
					"type": "string",
					"maxLength": 50,
					"description": "Customer project name."
				},
				"projectNumber": {
					"type": "string",
					"maxLength": 50,
					"description": "Project number."
				},
				"sendersReference": {
					"type": "string",
					"maxLength": 50,
					"description": "The sender's reference."
				},
				"receiversReference": {
					"type": "string",
					"maxLength": 50,
					"description": "The receiver's reference."
				},
				"goodsType": {
					"type": "string",
					"maxLength": 50,
					"description": "Type of goods at the order level."
				},
				"officeMessage": {
					"type": "string",
					"maxLength": 2048,
					"description": "Instructions for the office."
				},
				"officeExtraMessage": {
					"type": "string",
					"maxLength": 2048,
					"description": "Instructions for the office."
				},
				"officeExternalMessage": {
					"type": "string",
					"maxLength": 2048,
					"description": "Instructions for the office."
				},
				"driverInstructions": {
					"type": "string",
					"maxLength": 2048,
					"description": "Instructions for the driver."
				},
				"transportDate": {
					"type": "string",
					"format": "date",
					"description": "The transporter's first transport date, formatted as 'YYYY-MM-DD'. If no one is selected earliestPickupTime will be used. If there is no earliestPickupTime the date of import will be used."
				},
				"orderDimensions": {
					"type": "object",
					"additionalProperties": false,
					"properties": {
						"orderPackageQuantity": {
							"type": "integer",
							"description": "Set the number of transported parcels. Calculated if package dimensions are provided."
						},
						"orderWeightKgm": {
							"type": "number",
							"description": "Set weight of the order in kilograms. Calculated if package dimensions are provided."
						},
						"orderVolumeCbm": {
							"type": "number",
							"description": "Set volume of the order in cubic meters. Calculated if package dimensions are provided."
						},
						"orderEuropalletSpace": {
							"type": "number",
							"description": "Set europallet space of the order. Calculated if package dimensions are provided."
						},
						"orderLoadmeterMtr": {
							"type": "number",
							"description": "Set load meter of the order. Calculated if package dimensions are provided."
						}
					}
				},
				"transporterSpecificFields": {
					"type": "object",
					"additionalProperties": false,
					"description": "Fields specific to the transporter.",
					"properties": {
						"priceitems": {
							"type": "array",
							"description": "Transporter-specified price items requested by the transporter.",
							"items": {
								"type": "object",
								"additionalProperties": false,
								"properties": {
									"priceitemMappingCode": {
										"type": "string",
										"maxLength": 50,
										"description": "Mapped price item code."
									},
									"customerReference": {
										"type": "string",
										"maxLength": 50,
										"description": "Customer reference for the price item."
									},
									"state": {
										"type": "string",
										"enum": [
											"new",
											"update",
											"delete"
										],
										"maxLength": 50,
										"description": "Price items can be created, updated, or deleted."
									},
									"description": {
										"type": "string",
										"maxLength": 1024,
										"description": "Price item description."
									}
								}
							}
						},
						"extraDimension1": {
							"type": "number",
							"description": "Extra dimension 1."
						},
						"extraDimension2": {
							"type": "number",
							"description": "Extra dimension 2."
						},
						"extraDimension3": {
							"type": "number",
							"description": "Extra dimension 3."
						},
						"extraDimension4": {
							"type": "number",
							"description": "Extra dimension 4."
						},
						"extraDimension5": {
							"type": "number",
							"description": "Extra dimension 5."
						},
						"extraId1": {
							"type": "string",
							"maxLength": 50,
							"description": "Extra ID 1."
						},
						"extraId2": {
							"type": "string",
							"maxLength": 50,
							"description": "Extra ID 2."
						},
						"extraId3": {
							"type": "string",
							"maxLength": 50,
							"description": "Extra ID 3."
						},
						"extraId4": {
							"type": "string",
							"maxLength": 50,
							"description": "Extra ID 4."
						},
						"extraId5": {
							"type": "string",
							"maxLength": 50,
							"description": "Extra ID 5."
						},
						"regionMappingCode": {
							"type": "string",
							"maxLength": 50,
							"description": "Region mapping code."
						},
						"trailMappingCode": {
							"type": "string",
							"maxLength": 50,
							"description": "Trail mapping code."
						},
						"querySetMappingCode": {
							"type": "string",
							"maxLength": 50,
							"description": "Query set mapping code."
						},
						"readyForInvoicing": {
							"type": "boolean",
							"description": "Ready for invoicing. Only used if transporter specifies."
						},
						"readyForDispatching": {
							"type": "boolean",
							"description": "Ready for dispatching. Only used if transporter specifies."
						},
						"notToBeInvoiced": {
							"type": "boolean",
							"description": "Not to be invoiced. Only used if transporter specifies."
						},
						"hideUntilScanned": {
							"type": "boolean",
							"description": "Hide until scanned. Only used if transporter specifies."
						}
					}
				},
				"options": {
					"type": "array",
					"description": "Transporter-specified options selected on the order.",
					"items": {
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"optionMappingCode": {
								"type": "string",
								"maxLength": 50,
								"description": "Mapped option."
							},
							"selected": {
								"type": "boolean",
								"description": "Set to true to select the option."
							}
						}
					}
				},
				"addresses": {
					"type": "array",
					"description": "List of addresses related to the order.",
					"items": {
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"addressType": {
								"type": "string",
								"enum": [
									"pickup",
									"delivery"
								],
								"description": "Type of the address (e.g. pickup or delivery)"
							},
							"earliestTransportDateTime": {
								"type": "string",
								"format": "date-time",
								"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
								"description": "Earliest time for transport at the address in local time, formatted as 'YYYY-MM-DDTHH:MM:SS'."
							},
							"latestTransportDateTime": {
								"type": "string",
								"format": "date-time",
								"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
								"description": "Latest time for transport at the address in local time, formatted as 'YYYY-MM-DDTHH:MM:SS'."
							},
							"transporterCustomerCode": {
								"type": "string",
								"maxLength": 50,
								"description": "Use address information on a customer created by the transporter."
							},
							"transporterHubMappingCode": {
								"type": "string",
								"maxLength": 50,
								"description": "A hub used solo or with name, street address, zip code, city, and country."
							},
							"name": {
								"type": "string",
								"maxLength": 50,
								"description": "Company/person at the address. Required if sending address information."
							},
							"careOf": {
								"type": "string",
								"maxLength": 50,
								"description": "Care of company/person, if used by the transporter."
							},
							"streetAddress": {
								"type": "string",
								"maxLength": 50,
								"description": "Address street name and number. Required if sending address information."
							},
							"addressLine2": {
								"type": "string",
								"maxLength": 50,
								"description": "Address line 2, if used by the transporter."
							},
							"addressLine3": {
								"type": "string",
								"maxLength": 50,
								"description": "Address line 3, if used by the transporter."
							},
							"zipCode": {
								"type": "string",
								"maxLength": 50,
								"description": "Address zip code. Required if sending address information."
							},
							"city": {
								"type": "string",
								"maxLength": 50,
								"description": "Address city. Required if sending address information."
							},
							"countryCode": {
								"type": "string",
								"maxLength": 2,
								"minLength": 2,
								"pattern": "^[A-Z]{2}$",
								"description": "Address country code (ISO 3166-1 alpha-2). Required if sending address information."
							},
							"longitude": {
								"type": "number",
								"description": "Longitude of the address (GPS position)."
							},
							"latitude": {
								"type": "number",
								"description": "Latitude of the address (GPS position)."
							},
							"entreCode": {
								"type": "string",
								"maxLength": 50,
								"description": "Entrance code for the address."
							},
							"phoneNumber": {
								"type": "string",
								"maxLength": 50,
								"description": "Phone number for the address."
							},
							"emailAddress": {
								"type": "string",
								"format": "email",
								"maxLength": 50,
								"description": "Email address for the address."
							},
							"driverInstructions": {
								"type": "string",
								"maxLength": 255,
								"description": "Instructions for the driver regarding the address."
							}
						},
						"allOf": [
							{
								"if": {
									"properties": {
										"countryCode": {
											"enum": [
												"EE",
												"FI",
												"SE"
											]
										}
									}
								},
								"then": {
									"properties": {
										"zipCode": {
											"type": "string",
											"minLength": 5,
											"maxLength": 5
										}
									}
								}
							},
							{
								"if": {
									"properties": {
										"countryCode": {
											"enum": [
												"DK",
												"NO"
											]
										}
									}
								},
								"then": {
									"properties": {
										"zipCode": {
											"type": "string",
											"minLength": 4,
											"maxLength": 4
										}
									}
								}
							}
						]
					}
				},
				"packages": {
					"type": "array",
					"description": "Details about the packages/items with labels to be transported.",
					"items": {
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"customerReference": {
								"type": "string",
								"maxLength": 50,
								"description": "Customer reference."
							},
							"barcode": {
								"type": "string",
								"maxLength": 50,
								"description": "Unique identifier for the package (barcode)."
							},
							"packageTypeCode": {
								"type": "string",
								"maxLength": 50,
								"description": "Type of package (e.g., EUR, PC)."
							},
							"text": {
								"type": "string",
								"maxLength": 50,
								"description": "Package text."
							},
							"goodsType": {
								"type": "string",
								"maxLength": 50,
								"description": "Goods type in the package."
							},
							"dimensions": {
								"type": "object",
								"additionalProperties": false,
								"properties": {
									"quantity": {
										"type": "integer",
										"description": "Number of packages in this row (should be 1)."
									},
									"weightKgm": {
										"type": "number",
										"description": "Weight of the package in kilograms."
									},
									"volumeCbm": {
										"type": "number",
										"description": "Volume of the package in cubic meters."
									},
									"europalletSpace": {
										"type": "number",
										"description": "Europallet space occupied by the package."
									},
									"loadmeterMtr": {
										"type": "number",
										"description": "Load meter occupied by the package."
									},
									"widthMtr": {
										"type": "number",
										"description": "Package width in meters."
									},
									"heightMtr": {
										"type": "number",
										"description": "Package height in meters."
									},
									"depthMtr": {
										"type": "number",
										"description": "Package depth/length in meters."
									}
								}
							},
							"transporterSpecificFields": {
								"type": "object",
								"additionalProperties": false,
								"properties": {
									"extraDimension1": {
										"type": "number",
										"description": "Extra dimension 1."
									},
									"extraDimension2": {
										"type": "number",
										"description": "Extra dimension 2."
									},
									"extraDimension3": {
										"type": "number",
										"description": "Extra dimension 3."
									},
									"extraDimension4": {
										"type": "number",
										"description": "Extra dimension 4."
									},
									"extraDimension5": {
										"type": "number",
										"description": "Extra dimension 5."
									},
									"extraId1": {
										"type": "string",
										"maxLength": 255,
										"description": "Extra ID 1."
									},
									"extraId2": {
										"type": "string",
										"maxLength": 255,
										"description": "Extra ID 2."
									},
									"extraId3": {
										"type": "string",
										"maxLength": 255,
										"description": "Extra ID 3."
									},
									"extraId4": {
										"type": "string",
										"maxLength": 255,
										"description": "Extra ID 4."
									},
									"extraId5": {
										"type": "string",
										"maxLength": 255,
										"description": "Extra ID 5."
									}
								}
							}
						}
					}
				},
				"dangerousGoods": {
					"type": "array",
					"items": {
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"unNumber": {
								"type": "integer",
								"minimum": 1,
								"maximum": 9999,
								"description": "UN number of dangerous goods."
							},
							"properShippingName": {
								"type": "string",
								"maxLength": 50,
								"description": "Proper shipping name of dangerous goods."
							},
							"class": {
								"type": "string",
								"pattern": "^(?:[1-9](?:\\.\\d{1,2})?)$",
								"maxLength": 50,
								"description": "Class of dangerous goods."
							},
							"packingGroup": {
								"type": "string",
								"enum": [
									"I",
									"II",
									"III"
								],
								"description": "Packing group of dangerous goods, Value can be 'I', 'II', or 'III'."
							},
							"amount": {
								"type": "number",
								"description": "Amount of dangerous goods."
							},
							"unit": {
								"type": "string",
								"maxLength": 50,
								"description": "Unit of measurement (e.g., kg, liter)."
							},
							"barcodes": {
								"type": "array",
								"items": {
									"type": "string",
									"description": "Barcode on package with dangerous goods"
								},
								"minItems": 1,
								"uniqueItems": true,
								"description": "Array of unique barcodes."
							}
						}
					}
				},
				"documents": {
					"type": "array",
					"items": {
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"documentType": {
								"type": "string",
								"enum": [
									"edi",
									"freightbill",
									"packagelabel"
								],
								"maxLength": 50,
								"description": "Type of document."
							},
							"dataBase64": {
								"type": "string",
								"description": "Base64 encoded document. Opter prefer PDFs. "
							},
							"url": {
								"type": "string",
								"maxLength": 255,
								"description": "URL to the document. Opter prefer PDFs."
							},
							"fileName": {
								"type": "string",
								"maxLength": 50,
								"description": "File name with file extension of the document."
							},
							"comment": {
								"type": "string",
								"maxLength": 255,
								"description": "Comment on the document."
							}
						},
						"oneOf": [
							{
								"required": [
									"dataBase64"
								]
							},
							{
								"required": [
									"url"
								]
							}
						]
					}
				},
				"if": {
					"properties": {
						"packages": {
							"type": "array",
							"maxItems": 0
						}
					}
				},
				"then": {
					"required": [
						"orderDimensions"
					]
				},
				"else": {
					"not": {
						"required": [
							"orderDimensions"
						]
					}
				}
			}
		}
	}
}