Order Items API
This document provides details about the Order Items API endpoints, which allow you to list, retrieve, add, update, and delete items within an order.
List Order Items
Returns a paginated list of items in an order, with optional filtering by status.
URL: /v1/orders/{orderId}/items
Method: GET
Auth required: Yes
Parameters:
| Name | Located in | Description | Required | Type |
|---|---|---|---|---|
| orderId | path | Order ID or order number | Yes | string |
| status | query | Filter items by status | No | string |
| limit | query | Number of items per page (default: 20) | No | integer |
| offset | query | Offset for pagination (default: 0) | No | integer |
Example Request:
GET /v1/orders/ORD12345/items
Success Response:
Code: 200 OK
Content example:
{
"data": [
{
"item_id": "PROD123",
"sku": "PROD123-VAR1",
"name": "Product Name",
"quantity": 2,
"price": 29.99,
"status": "pending",
"image_url": "https://example.com/product-123.jpg",
"properties": {
"color": "blue",
"size": "medium"
},
"created_at": "2023-01-15T12:00:00Z",
"updated_at": "2023-01-15T12:00:00Z"
},
{
"item_id": "PROD456",
"sku": "PROD456",
"name": "Another Product",
"quantity": 1,
"price": 15.99,
"status": "pending",
"image_url": null,
"properties": {},
"created_at": "2023-01-15T12:00:00Z",
"updated_at": "2023-01-15T12:00:00Z"
}
],
"pagination": {
"total": 2,
"limit": 20,
"offset": 0
}
}
Error Response:
Code: 404 Not Found
Content:
{
"error": {
"code": "ORDER_NOT_FOUND",
"message": "No order found with ID or order number ORD12345"
}
}
Get Order Item
Returns detailed information about a specific item in an order.
URL: /v1/orders/{orderId}/items/{itemId}
Method: GET
Auth required: Yes
Parameters:
| Name | Located in | Description | Required | Type |
|---|---|---|---|---|
| orderId | path | Order ID or order number | Yes | string |
| itemId | path | Item ID | Yes | string |
Example Request:
GET /v1/orders/ORD12345/items/PROD123
Success Response:
Code: 200 OK
Content example:
{
"item_id": "PROD123",
"sku": "PROD123-VAR1",
"name": "Product Name",
"quantity": 2,
"price": 29.99,
"status": "pending",
"image_url": "https://example.com/product-123.jpg",
"properties": {
"color": "blue",
"size": "medium"
},
"created_at": "2023-01-15T12:00:00Z",
"updated_at": "2023-01-15T12:00:00Z"
}
Error Response:
Code: 404 Not Found
Content:
{
"error": "Item not found",
"message": "No item found with ID PROD123 in order ORD12345"
}
Add Item to Order
Adds a new item to an existing order.
URL: /v1/orders/{orderId}/items
Method: POST
Auth required: Yes
Parameters:
| Name | Located in | Description | Required | Type |
|---|---|---|---|---|
| orderId | path | Order ID or order number | Yes | string |
| product_id | body | Product ID (becomes item_id) | Yes | string |
| variant_id | body | Variant ID (becomes sku) | No | string |
| name | body | Product name | No | string |
| quantity | body | Quantity (must be positive) | Yes | number |
| price | body | Price per unit | No | number |
| image_url | body | URL of the product image | No | string |
| properties | body | Additional product properties | No | object |
Note: If an item with the same product_id already exists in the order, the quantity will be added to the existing item instead of creating a new one.
Example Request:
POST /v1/orders/ORD12345/items
{
"product_id": "PROD123",
"variant_id": "PROD123-VAR1",
"name": "Product Name",
"quantity": 2,
"price": 29.99,
"image_url": "https://example.com/product-123.jpg",
"properties": {
"color": "blue",
"size": "medium"
}
}
Success Response:
Code: 201 Created
Content example:
{
"item_id": "PROD123",
"sku": "PROD123-VAR1",
"name": "Product Name",
"quantity": 2,
"price": 29.99,
"status": "pending",
"image_url": "https://example.com/product-123.jpg",
"properties": {
"color": "blue",
"size": "medium"
},
"created_at": "2023-01-15T12:00:00Z",
"updated_at": "2023-01-15T12:00:00Z"
}
Error Responses:
Code: 400 Bad Request
Content:
{
"error": "Invalid request",
"message": "Missing required field: product_id"
}
OR
{
"error": "Invalid request",
"message": "Item quantity must be a positive number"
}
Code: 404 Not Found
Content:
{
"error": {
"code": "ORDER_NOT_FOUND",
"message": "No order found with ID or order number ORD12345"
}
}
Code: 409 Conflict
Content:
{
"error": "Conflict",
"message": "Cannot add items to an order with status \"shipped\""
}
Note: Items can only be added to orders with status "draft", "pending", or "created".
Update Order Item
Updates an existing item in an order.
URL: /v1/orders/{orderId}/items/{itemId}
Method: PUT
Auth required: Yes
Parameters:
| Name | Located in | Description | Required | Type |
|---|---|---|---|---|
| orderId | path | Order ID or order number | Yes | string |
| itemId | path | Item ID | Yes | string |
| name | body | Product name | No | string |
| quantity | body | Quantity (must be positive) | No | number |
| price | body | Price per unit | No | number |
| status | body | Item status | No | string |
| image_url | body | URL of the product image | No | string |
| properties | body | Additional product properties | No | object |
Example Request:
PUT /v1/orders/ORD12345/items/PROD123
{
"quantity": 3,
"price": 27.99,
"status": "picked",
"image_url": "https://example.com/updated-product-123.jpg"
}
Success Response:
Code: 200 OK
Content example:
{
"item_id": "PROD123",
"sku": "PROD123-VAR1",
"name": "Product Name",
"quantity": 3,
"price": 27.99,
"status": "picked",
"image_url": "https://example.com/updated-product-123.jpg",
"properties": {
"color": "blue",
"size": "medium"
},
"created_at": "2023-01-15T12:00:00Z",
"updated_at": "2023-01-15T13:30:00Z"
}
Error Responses:
Code: 400 Bad Request
Content:
{
"error": "Invalid request",
"message": "Item quantity must be a positive number"
}
Code: 404 Not Found
Content:
{
"error": "Item not found",
"message": "No item found with ID PROD123 in order ORD12345"
}
Code: 409 Conflict
Content:
{
"error": "Conflict",
"message": "Cannot update items in an order with status \"shipped\""
}
Note: Items can only be updated in orders with status "draft", "pending", "created", or "processing".
Remove Item from Order
Removes an item from an order.
URL: /v1/orders/{orderId}/items/{itemId}
Method: DELETE
Auth required: Yes
Parameters:
| Name | Located in | Description | Required | Type |
|---|---|---|---|---|
| orderId | path | Order ID or order number | Yes | string |
| itemId | path | Item ID | Yes | string |
Example Request:
DELETE /v1/orders/ORD12345/items/PROD123
Success Response:
Code: 204 No Content
Error Responses:
Code: 404 Not Found
Content:
{
"error": "Item not found",
"message": "No item found with ID PROD123 in order ORD12345"
}
Code: 409 Conflict
Content:
{
"error": "Conflict",
"message": "Cannot remove items from an order with status \"shipped\""
}
Note: Items can only be removed from orders with status "draft", "pending", or "created".
Item Fields Reference
The following table describes all fields available in an order item:
| Field Name | Type | Required | Description |
|---|---|---|---|
| item_id | string | Yes | Unique identifier for the item |
| sku | string | No | Stock keeping unit (variant ID) |
| name | string | No | Product name |
| quantity | number | Yes | Quantity of the item (positive) |
| price | number | No | Price per unit |
| status | string | No | Current status of the item |
| image_url | string | No | URL of the product image |
| properties | object | No | Additional product properties |
| collected_product | object | No | Details of the actual product collected during fulfillment |
| created_at | string | Yes | ISO 8601 timestamp of creation |
| updated_at | string | Yes | ISO 8601 timestamp of last update |
Note: The image_url field is optional and can be null. When provided, it should be a valid URL pointing to the product image.
Collected Product Information
The collected_product field contains detailed information about the actual product that was picked/collected during fulfillment. This field is populated when an item has been physically picked and provides comprehensive details about what was actually collected.
Collected Product Structure
The collected_product object includes:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the collected product |
amount | number | Actual quantity collected |
shopkeeper_timestamp | string (date-time) | When the item was collected by the picker |
collected | boolean | Whether the item was successfully collected |
ean | string | EAN/barcode of the collected product |
sku | string | SKU of the collected product |
name | string | Name of the collected product |
price | number | Product price |
images | integer | Number of images available |
image_guid | array | Array of image objects for the collected product |
Example with Collected Product
{
"item_id": "PROD123",
"name": "Original Product",
"quantity": 2,
"price": 29.99,
"status": "picked",
"collected_product": {
"id": "COLLECTED-456",
"amount": 2,
"shopkeeper_timestamp": "2023-06-01T14:30:00Z",
"collected": true,
"ean": "5000112637922",
"sku": "PROD123-VAR1",
"name": "Actual Collected Product",
"price": 29.99,
"images": 1,
"image_guid": [
{
"id": "img-collected-456",
"url": "https://example.com/collected-product.jpg",
"width": 800,
"height": 600,
"mime_type": "image/jpeg"
}
]
}
}
Image Handling
The Unified Order Service provides automatic image handling for order items across different channel types. Here's how images are processed:
Image URL Support
Order items can include product images in multiple ways:
- Direct
image_urlfield - At the top level of the item - Properties
image_url- Inside thepropertiesobject - Substitute suggestions - Each substitute item can have its own
image_url
Priority order: properties.image_url > image_url field
Channel-Specific Image Processing
Drone API Integration
When orders are converted to Drone API format, the image handling is automatically enhanced:
Items with images get converted to the
image_guidstructure with default metadata:images: 1(count)image_guidarray with:id: Generated from item ID (e.g., "img-item-123")url: Original image URLwidth: 1024 (default)height: 1024 (default)mime_type: "image/png" (default)media_type_code: "PICTURE"file_size: 0 (default)created_at: Current timestampupdated_at: Current timestamp
Items without images get:
images: 0image_guid: [](empty array)
Example: Order with Images
Input (Salesforce/Standard format):
{
"items": [
{
"item_id": "354645165",
"name": "Coca Cola Zero 1.25 Ltr",
"quantity": 2,
"price": 1.5,
"properties": {
"image_url": "https://example.com/coca-cola-zero.jpg",
"sub_suggestions": [
{
"item_id": "354645164",
"name": "Coca Cola Original Taste 1.25 Ltr",
"image_url": "https://example.com/coca-cola-original-taste.jpg"
}
]
}
},
{
"item_id": "654245842",
"name": "British Chicken Tikka Masala",
"quantity": 1,
"price": 4.2,
"properties": {
"image_url": null
}
}
]
}
Output (Drone API format):
{
"products": [
{
"id": "354645165",
"name": "Coca Cola Zero 1.25 Ltr",
"images": 1,
"image_guid": [
{
"id": "img-354645165",
"url": "https://example.com/coca-cola-zero.jpg",
"width": 1024,
"height": 1024,
"mime_type": "image/png",
"media_type_code": "PICTURE",
"file_size": 0,
"created_at": "2023-06-01T12:00:00Z",
"updated_at": "2023-06-01T12:00:00Z"
}
]
},
{
"id": "654245842",
"name": "British Chicken Tikka Masala",
"images": 0,
"image_guid": []
}
]
}
Best Practices
- Use valid URLs: Ensure image URLs are accessible and return valid image content
- Include images for better picking: Products with images improve picker accuracy and speed
- Optimize image sizes: While the system uses default dimensions (1024x1024), consider the actual image optimization on your end
- Handle missing images gracefully: The system automatically handles items without images
- Use HTTPS URLs: Preferred for security and compatibility
Supported Channel Types
Image handling is currently supported for:
- ✅ Salesforce channels - Full support for image_url in properties and substitutes
- ✅ Drone API channels - Automatic conversion to image_guid structure
- ✅ Base/Standard format - Direct image_url field support
- 🔄 Other channel types - May have varying levels of support
For channel-specific image requirements, consult the individual channel documentation.
Substitution Support
Overview
The UOS system supports product substitutions during the picking process. For items to show substitution options in the picker app, they must be properly flagged as substitutable in the order data.
Required Fields for Substitutable Items
For an item to support substitutions, at least one of the following must be provided:
| Field | Location | Type | Description |
|---|---|---|---|
substitutable | item level | boolean | Main substitution flag - set to true |
allowed_substitutions | item level | array | Array of substitute item IDs |
sub_enabled | properties | boolean | Alternative substitution flag - set to true |
sub_suggestions | properties | array | Array of detailed substitute information |
Salesforce Channel Requirements
⚠️ Important for Salesforce integrations: To ensure substitution options appear in the picker app, Salesforce channels must include substitution data in their order payloads.
Required Payload Structure
{
"items": [{
"item_id": "MAIN-PRODUCT-123",
"name": "Main Product",
"quantity": 1,
"price": 10.99,
"substitutable": true, // ✅ REQUIRED: Main substitution flag
"allowed_substitutions": ["SUB-PRODUCT-456", "SUB-PRODUCT-789"], // ✅ REQUIRED: Substitute IDs
"properties": {
"sub_enabled": true, // ✅ ALTERNATIVE: Can use this instead of substitutable
"sub_suggestions": [ // ✅ OPTIONAL: Detailed substitute info
{
"item_id": "SUB-PRODUCT-456",
"name": "Substitute Product 1",
"price": 9.99,
"barcode": "1234567890123",
"images": 2,
"image_guid": [
{
"id": "img-sub-456-1",
"url": "https://example.com/substitute-product-456.jpg",
"width": 800,
"height": 600,
"mime_type": "image/jpeg"
}
]
},
{
"item_id": "SUB-PRODUCT-789",
"name": "Substitute Product 2",
"price": 11.99,
"barcode": "9876543210987"
}
]
}
}]
}
Common Issues (QCOM-887 Type Problems)
❌ Problematic payload (substitutions won't appear):
{
"items": [{
"item_id": "MAIN-PRODUCT-123",
"substitutable": false, // ❌ Not enabled
"allowed_substitutions": [], // ❌ Empty
"properties": {
"sub_enabled": false, // ❌ Not enabled
"sub_suggestions": [] // ❌ Empty
}
}]
}
Troubleshooting Substitution Issues
If substitution options are not appearing in the picker app:
- Check order data - Verify that substitution flags are set correctly
- Review logs - Look for diagnostic messages about substitution flags
- Validate payload - Ensure at least one substitution field is properly populated
- Test with sample data - Use the correct payload structure above
Diagnostic Logging
The system logs substitution analysis for debugging:
INFO: Item PRODUCT-123 marked as substitutable: explicit=true, sub_enabled=true, has_suggestions=true, has_allowed_subs=true
DEBUG: Item PRODUCT-456 NOT substitutable: no substitution flags or data found
Substitution Data Transformation
The system automatically transforms substitution data between different formats:
- Simple format: Array of substitute item IDs
- Detailed format: Full substitute product information
- Picker app format: Enhanced with images and metadata
For detailed substitution workflow examples, see the Drone API Products documentation.