SKU Based Order Import
This guide explains how to use the SKU-based API to import line items from purchase orders (PO) and convert them into Transport Orders (Bookings) containing Order Items (Line Items) for SWAT route optimization.
Overview
The SKU Based Order Import API allows you to send detailed purchase order data, including specific Stock Keeping Unit (SKU) information, directly to the SWAT system. This data is used to:
- Create/Clone a Simulation: Initialize a new simulation environment based on provided parameters.
- Import Order Items: Create line items (Order Items) derived from the purchase order lines.
- Link SKUs: Automatically identify or define SKUs associated with each order item, ensuring accurate demand (weight, volume) and handling constraints.
Strategic Value: SKU/Line-Item vs. Basic Booking
Understanding when to use the SKU-based import (Line Items) versus the standard Booking-based import is critical for designing a robust integration.
For the Integrator: Data Granularity
| Feature | Basic Booking Import | SKU Based Order Import |
|---|---|---|
| Input Data | Pre-calculated total weight/volume per stop. | Raw line items (e.g., "10x Item A", "5x Item B"). |
| Master Data | Not required. | Requires SKU Master (dimensions, constraints). |
| Complexity | Low. simple mapping of order -> stop. | Medium. Requires managing SKU catalog and composition logic. |
| Traceability | Limited to "Order Ref". | Full visibility of every item on the truck. |
Key Takeaway: Use SKU import when your upstream system (ERP/WMS) has detailed product data but lacks the logic to calculate total shipment volume or group orders effectively.
For the Planner: Operational Flexibility
From a logistics planning perspective, working with Line Items and SKUs unlocks advanced capabilities:
-
Automated Order Composition (Grouping):
- Challenge: A customer orders 50 items. The ERP sends 50 lines.
- Solution: The system automatically groups these into a single transport task, eliminating manual consolidation and preventing the optimizer from visiting the same customer 50 times.
-
Partial Delivery:
- Challenge: An order cannot be fully serviced due to capacity or time constraints.
- Solution: With
partial_allowedenabled, the system permits partial delivery of the transport order, ensuring maximum fulfillment even when complete service isn't possible.
-
Automatic Unit Conversion (Boxes to Capacity):
- Challenge: Orders come in business units (e.g., "10x Small Box", "5x Large Box"), but vehicles have physical limits (e.g., "2000kg", "15m³").
- Solution: The system uses the SKU master data to automatically translate these business units into physical demand. A "Small Box" is instantly converted to its specific weight and volume, and a "Large Box" to its own. The final Transport Order aggregates these precise physical values (Total kg, Total cbm), ensuring the vehicle is filled efficiently without exceeding any physical limit.
-
Handling Constraints:
- Challenge: Frozen goods cannot be on a non-refrigerated truck.
- Solution: SKU categories (e.g.,
frozen,hazardous) can automatically enforce vehicle compatibility rules, reducing the risk of compliance violations.
What is a SKU?
SKU (Stock Keeping Unit) represents a distinct type of item for sale or delivery. It acts as a master catalog entry containing static properties such as:
- Physical Attributes: Weight, volume, and dimensions (per unit and per packaging).
- Classification: Category (e.g., ambient, chilled) and handling type (e.g., fragile, hazardous).
- Identification: External ID, name, batch, and serial numbers.
When importing orders, Order Items (Line Items) reference these SKUs to automatically inherit their demand/capacity requirements (e.g., how much space they take up in a vehicle).
For more details on the SKU model, refer to the SKU API Documentation.
Simplified Item Management
To save you time, the system automatically builds your product catalog as you import orders:
- Automatic Detection: When you send an order, we check if we already know the product (by its
external_idor SKU code). - New Products: If it's a new product we haven't seen before, the system automatically creates a master record for it using the details (size, weight, category) from the order.
- Master Data Safety: If the product already exists in your catalog, we ignore the product details in the daily order file and use your established Master Data instead. This ensures that a typo in a daily order file won't accidentally corrupt your master product definitions.
Scope & Uniqueness
Both SKUs and Order Items are scoped to a specific SWAT Project.
- Project Scope: Data is isolated within a project. An SKU defined in Project A is not visible to Project B.
- Identifiers: Fields like
external_id(for SKUs) andorder_ref(for Order Items) are typically unique within the context of a single project, allowing you to map your internal ERP/WMS identifiers directly to SWAT resources.
For more details on the Order Item model, refer to the Order Item API Documentation.
Data Model Relationships
The following diagram illustrates how these entities interact within the system:
- SKU: Master data defining the product. View API
- Order Item: A specific line item request to move a quantity of an SKU. View API
- Booking: The transport order or shipment. View API
- Assigned Item: Links a portion (or all) of an Order Item to a Booking. View API
- Simulation: The optimization environment containing the bookings.
- Vehicle: The resource executing the Transport Orders. View API
Payload Structure
The API accepts a JSON payload with the following top-level structure:
project(integer): The ID of the SWAT project.simulation_clone_parameters(object): Parameters to configure the simulation timeframe.order_items(array): A list of purchase order lines to be imported.
Simulation Clone Parameters
Defines the scope of the simulation to be generated from these orders. See How is a Simulation Identified? to understand when a new simulation is created versus when an existing one is reused based on these parameters.
project_id(integer): Should match the top-level project ID.start_time(ISO-8601 datetime): The start of the simulation window.end_time(ISO-8601 datetime): The end of the simulation window.
Order Items
Each object in the order_items array represents a line item from a purchase order.
The system does not validate order_ref or order_line for uniqueness. Every item in the order_items list will be imported as a new Order Item. If you re-send the same data, duplicate Order Items will be created. Please ensure your integration filters out previously sent orders to avoid unintended duplication.
Core Fields
order_ref(string): The purchase order reference number (e.g., "PO-97970").order_line(string | integer): Optional. Line number within the purchase order (e.g., 10, "L-01").order_date(date string): The date of the order (YYYY-MM-DD).status(string): Initial status of the item (e.g., "initial").quantity(float/integer): The quantity of the SKU to be moved.
Timing
start_time(ISO-8601 datetime): Earliest allowable delivery time.end_time(ISO-8601 datetime): Latest allowable delivery time.load_start_time(ISO-8601 datetime): Earliest allowable pickup/loading time.load_end_time(ISO-8601 datetime): Latest allowable pickup/loading time.
Customer & Location
customer_name(string): Name of the customer receiving the order.customer_code(string): Unique code for the customer.location_name(string): Name of the delivery location.ship_to(string): Identifier for the destination.ship_from(string): Identifier for the origin (pickup) location.load_location_name(string): Name of the pickup location.- Coordinates:
pickup_location_lat,pickup_location_lon(float): GPS coordinates for pickup.dropoff_location_lat,dropoff_location_lon(float): GPS coordinates for drop-off.
SKU Details
The sku object defines the product being transported. If partial_allowed is true, the system can plan a partial delivery for this item if the full quantity cannot be accommodated.
external_id(string): Unique identifier for the SKU.name(string): Human-readable name of the product.category(string): Product category (e.g., "ambient", "chilled").handling_type(string): Special handling instructions (e.g., "standard").partial_allowed(boolean): Whether partial delivery of this item's quantity is allowed.demand(object):weight(float): Weight per unit.volume(float): Volume per unit.
Location Resolution Logic
The system resolves pickup and drop-off locations using the following logic:
-
Operations Location (
external_id/code):- If a location identifier (e.g.,
ship_from,ship_to,load_location_code) is provided and matches an existing Operations Location in the project, the system links the order to that pre-defined location. - Precedence: The coordinates, service times, and constraints defined in the Operations Location take precedence over any raw
lat/lonvalues in the payload. This is best for recurring locations like warehouses or retail outlets.
- If a location identifier (e.g.,
-
Ad-hoc Coordinates (
lat/lon):- If no matching Operations Location is found, or if the identifiers are omitted, the system typically uses the provided
pickup_location_lat/lonanddropoff_location_lat/lonto define a one-time location for this specific order. - Note: Ensure your API proxy or import configuration is set to handle ad-hoc coordinates if your operation involves non-fixed locations.
- If no matching Operations Location is found, or if the identifiers are omitted, the system typically uses the provided
Order Composition Logic
When you import multiple order items, the system automatically analyzes and groups them to optimize transport planning. This process creates Composite Bookings from related line items.
Grouping Behavior
The system treats multiple line items as a single Transport Order (Booking) if they share the exact same:
- Origin (
ship_fromlocation). - Destination (
ship_tolocation). - Service Time Windows:
- Pickup window (
load_start_time&load_end_time). - Delivery window (
start_time&end_time).
- Pickup window (
How It Works
- Consolidation: Instead of creating separate bookings for every SKU (e.g., 10 boxes of Tea and 5 boxes of Coffee), the system consolidates them into one booking.
- Aggregated Demand: The weight and volume of all items are summed up to determine the total vehicle capacity required.
- Traceability: The resulting booking retains details of all included SKUs in its remarks or metadata, ensuring drivers know exactly what they are transporting.
This logic prevents efficient routes from being fragmented into multiple stops for the same customer and ensures the vehicle is loaded with the correct total shipment.
Example Request
{
"project": 904,
"simulation_clone_parameters": {
"project_id": 904,
"start_time": "2026-02-09T08:00:00+08:00",
"end_time": "2026-02-09T20:00:00+08:00"
},
"order_items": [
{
"quantity": 50,
"start_time": "2026-02-09T10:00:00+08:00",
"end_time": "2026-02-09T14:00:00+08:00",
"customer_name": "LION CITY RETAIL",
"customer_code": "SG-RET-001",
"location_name": "Lion City Retail - Orchard Branch",
"ship_to": "LOC-SG-ORCH-01",
"ship_from": "SG-MAIN-WH",
"load_start_time": "2026-02-09T07:00:00+08:00",
"load_end_time": "2026-02-09T08:30:00+08:00",
"load_location_name": "Jurong Main Warehouse",
"pickup_location_lat": 1.3329,
"pickup_location_lon": 103.7436,
"dropoff_location_lat": 1.3048,
"dropoff_location_lon": 103.8318,
"status": "initial",
"order_ref": "PO-SG-2026-001",
"order_line": 1,
"order_date": "2026-02-08",
"sku": {
"external_id": "SKU-BEV-001",
"name": "Jasmine Green Tea 500ml (Ctn)",
"category": "ambient",
"handling_type": "standard",
"partial_allowed": true,
"demand": {
"weight": 12.0,
"volume": 0.03
}
}
},
{
"quantity": 20,
"start_time": "2026-02-09T11:00:00+08:00",
"end_time": "2026-02-09T16:00:00+08:00",
"customer_name": "MARINA BAY SANDS HOSPITALITY",
"customer_code": "SG-HOSP-005",
"location_name": "MBS Receiving Bay",
"ship_to": "LOC-SG-MBS-RCV",
"ship_from": "SG-MAIN-WH",
"load_start_time": "2026-02-09T07:00:00+08:00",
"load_end_time": "2026-02-09T08:30:00+08:00",
"load_location_name": "Jurong Main Warehouse",
"pickup_location_lat": 1.3329,
"pickup_location_lon": 103.7436,
"dropoff_location_lat": 1.2834,
"dropoff_location_lon": 103.8607,
"status": "initial",
"order_ref": "PO-SG-2026-002",
"order_line": 1,
"order_date": "2026-02-08",
"sku": {
"external_id": "SKU-FRZ-099",
"name": "Premium Vanilla Ice Cream Tub",
"category": "frozen",
"handling_type": "standard",
"partial_allowed": true,
"demand": {
"weight": 5.0,
"volume": 0.01
}
}
}
]
}
Response Structure
The API returns a JSON object containing the status of the operation and details about the created resources.
status: "success" or "error".data:simulation_id: ID of the simulation where orders were imported.processor_id: ID of the background processor handling the optimization (if applicable).booking_ids: List of IDs of the created/updated Bookings.booking_details: A dictionary mapping Booking IDs to their constituent Order Items. This provides full traceability of which Order Items were grouped into which Transport Order.
Example Response
{
"status": "success",
"data": {
"simulation_id": 233251,
"processor_id": null,
"booking_ids": [101, 102],
"booking_details": {
"101": [
{
"order_ref": "PO-SG-2026-001",
"order_line": 1,
"order_item": "/api/v2/orderitem/501/"
},
{
"order_ref": "PO-SG-2026-001",
"order_line": 2,
"order_item": "/api/v2/orderitem/502/"
}
],
"102": [
{
"order_ref": "PO-SG-2026-002",
"order_line": 1,
"order_item": "/api/v2/orderitem/503/"
}
]
}
}
}