Order Workflow Tasks
Order tasks are used to create, update, and delete Orders.
Create Order
task: "Order/Create@1"
name: createOrder
inputs:
values:
billToContactId: "{{ billToContactId }}"
customValues: "{{ customValues }}"
divisionId: "{{ divisionId }}"
employeeContactId: "{{ employeeContactId }}"
entityTypeId: "{{ entityTypeId }}"
equipmentTypeId: "{{ equipmentTypeId }}"
lastOrderStatusModified: "{{ lastOrderStatusModified }}"
orderNumber: "{{ orderNumber }}"
orderStatusId: "{{ orderStatusId }}"
orderType: "{{ orderType }}"
salespersonContactId: "{{ salespersonContactId }}"
trackingNumber: "{{ trackingNumber }}"
outputs:
- name: order
mapping: "order"
Get Order
task: "Order/Get@1"
name: getOrder
inputs:
orderId: "123"
outputs:
- name: order
mapping: "order"
Update Order
task: "Order/Update@1"
name: updateOrder
inputs:
orderId: "123"
values:
billToContactId: "{{ billToContactId }}"
customValues: "{{ customValues }}"
divisionId: "{{ divisionId }}"
employeeContactId: "{{ employeeContactId }}"
entityTypeId: "{{ entityTypeId }}"
equipmentTypeId: "{{ equipmentTypeId }}"
lastOrderStatusModified: "{{ lastOrderStatusModified }}"
orderNumber: "{{ orderNumber }}"
orderStatusId: "{{ orderStatusId }}"
orderType: "{{ orderType }}"
salespersonContactId: "{{ salespersonContactId }}"
trackingNumber: "{{ trackingNumber }}"
Delete Order
task: "Order/Delete@1"
name: deleteOrder
inputs:
orderId: "123"
Copy Order
Creates a full copy of an existing order including entities, charges, commodities, and custom values. Tracking events are not copied.
Copy Options
| Option | Type | Required | Description |
|---|---|---|---|
orderId | int | Yes | The source order to copy |
orderType | OrderTypes | No | Override the order type on the copy. If not provided, keeps the original. |
orderStatusId | int | No | Override the order status on the copy. If not provided, keeps the original. |
trackingNumber | string | No | Set the tracking number for the new order. If not provided, defaults to null. |
Basic Copy
task: "Order/Copy@1"
name: copyOrder
inputs:
orderId: "{{ orderId }}"
outputs:
- name: newOrder
mapping: "order"
Copy with Overrides
task: "Order/Copy@1"
name: copyOrder
inputs:
orderId: "{{ orderId }}"
orderType: "Quote"
orderStatusId: "{{ newStatusId }}"
trackingNumber: "{{ trackingNumber }}"
outputs:
- name: newOrder
mapping: "order"
What the new order receives
- New order number (auto-generated)
- All OrderEntities (shipper, consignee, etc.)
- All Charges copied with
ChargeStatus.Open - All Commodities (full deep copy)
- Custom values with
copiedFromOrderIdandcopyOperationDatemetadata
Split Order
Splits an order into two orders by distributing commodities based on quantity (pieces) or weight. The new order receives copies of the original order's entities, charges (set to Open status), and custom values. Tracking events are not copied.
Split Options
| Option | Type | Description |
|---|---|---|
splitBy | string | How to split: "Quantity" (by pieces) or "Weight" (by weight) |
ratio | decimal | Proportional split (0-1 exclusive). Original keeps this fraction. Cannot be used with maxValue. |
maxValue | decimal | Maximum value for the original order. Overflow goes to the new order. Cannot be used with ratio. |
maxValueWeightUnit | string | Weight unit for maxValue when splitBy is "Weight". Required in that case. Values: "Kg" or "Lb". Commodity weights are converted to this unit for comparison. |
Split by Ratio
task: "Order/Split@1"
name: splitOrder
inputs:
orderId: "{{ orderId }}"
options:
splitBy: "Quantity"
ratio: 0.5
outputs:
- name: newOrder
mapping: "order"
Split by Max Value
task: "Order/Split@1"
name: splitOrder
inputs:
orderId: "{{ orderId }}"
options:
splitBy: "Weight"
maxValue: 500
maxValueWeightUnit: "Kg"
outputs:
- name: newOrder
mapping: "order"
Behavior
- By Quantity with Ratio: Each commodity's pieces are split proportionally. Original keeps
ceil(pieces * ratio). - By Quantity with MaxValue: Original keeps commodities up to
maxValuetotal pieces. Commodities at the boundary are split. - By Weight with Ratio: Multi-piece commodities split by pieces proportionally. Single-piece commodities split weight directly.
- By Weight with MaxValue: Original keeps commodities up to
maxValuetotal weight. Boundary commodities are split by pieces or weight.
What the new order receives
- New order number (auto-generated)
- All OrderEntities (shipper, consignee, etc.)
- All Charges copied with
ChargeStatus.Open - Split commodity portions
- Custom values with
splitFromOrderIdandsplitOperationDatemetadata
Transition Order
Triggers a transition on the active Flow workflow for an order. Can either invoke a specific named transition or re-evaluate all eligible transitions from the current state.
Use this task in scheduled trigger workflows to handle time-based transitions (e.g., marking orders as overdue) or in other workflows that need to programmatically advance an order's state.
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | int | Yes | The order to transition |
transitionName | string | No | The name of the transition to invoke. If omitted, the engine re-evaluates all eligible transitions from the current state using standard priority resolution. |
Output
| Field | Type | Description |
|---|---|---|
transitioned | boolean | Whether the transition was executed |
fromState | string | The state the order was in before (null if no transition occurred) |
toState | string | The state the order transitioned to (null if no transition occurred) |
transitionName | string | The name of the transition that executed (null if no transition occurred) |
YAML Structure
Named Transition
task: "Order/Transition@1"
name: transitionOrder
inputs:
orderId: "{{ orderId }}"
transitionName: "inTransit_to_overdue"
outputs:
- name: result
mapping: "transition"
Re-evaluate Flow
task: "Order/Transition@1"
name: reevaluateOrder
inputs:
orderId: "{{ orderId }}"
outputs:
- name: result
mapping: "transition"
Behavior
Common:
- The task respects all Flow engine rules: consumed events, cascade depth, condition evaluation
- If the order is in a
isFinalstate,transitionedreturnsfalse - Cascading transitions may occur up to the flow's
maxCascadeDepth— the output reflects only the first transition - Conditions are always evaluated — if they fail,
transitionedreturnsfalse
Named mode (with transitionName):
- Only the specified transition is attempted
- If the order is not in the transition's
fromstate,transitionedreturnsfalse - If the transition has
trigger: "manual", it executes as if invoked by the system (no user confirmation prompt) - If the specified
transitionNamedoes not exist in the active Flow, the task throws an error
Re-evaluate mode (without transitionName):
- All eligible transitions from the current state are evaluated using standard priority resolution
- The highest-priority transition whose conditions pass is executed
- If no conditions pass for any eligible transition,
transitionedreturnsfalse
Example: Named Transition — Scheduled Overdue Detection
A scheduled workflow that targets a specific transition by name:
workflow:
name: "Daily Overdue Order Check"
workflowId: "e5f6a7b8-c9d0-1234-ef01-567890123456"
isActive: true
workflowType: "Standard"
executionMode: "Async"
schedules:
- cron: "0 6 * * *"
displayName: "Daily at 6 AM"
activities:
- name: "findAndTransitionOverdueOrders"
description: "Find orders past due date and transition to overdue"
steps:
- task: "Order/Search@1"
name: findOverdueOrders
inputs:
filter: "statusStage: InProgress AND dueDate: [* TO NOW-1DAY]"
orderType: "ParcelShipment"
outputs:
- name: orders
mapping: "orders"
- task: "foreach"
inputs:
collection: "{{ findOverdueOrders.orders }}"
item: "order"
steps:
- task: "Order/Transition@1"
name: markOverdue
inputs:
orderId: "{{ order.orderId }}"
transitionName: "inProgress_to_overdue"
continueOnError: true
Example: Re-evaluate — Timer-Based Flow Check
A scheduled workflow that re-evaluates flows without specifying a transition. The engine determines which transition (if any) should fire based on current state and conditions:
workflow:
name: "Hourly Flow Re-evaluation"
workflowId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
isActive: true
workflowType: "Standard"
executionMode: "Async"
schedules:
- cron: "0 * * * *"
displayName: "Every hour"
activities:
- name: "reevaluateInProgressOrders"
description: "Re-evaluate flow for in-progress orders"
steps:
- task: "Order/Search@1"
name: findOrders
inputs:
filter: "statusStage: InProgress"
orderType: "ParcelShipment"
outputs:
- name: orders
mapping: "orders"
- task: "foreach"
inputs:
collection: "{{ findOrders.orders }}"
item: "order"
steps:
- task: "Order/Transition@1"
name: reevaluate
inputs:
orderId: "{{ order.orderId }}"
continueOnError: true
Add Tracking Event to Order
Adds a tracking event to an order by event definition name or ID. If the event definition does not exist, it can be auto-created. The tracking event is automatically linked to all first-level commodities of the order (commodities where ContainerCommodityId is null).
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | int | Yes | The order to add the tracking event to |
organizationId | int | Yes | The organization ID |
eventDefinitionName | string | Conditional | Name of the event definition (required if eventDefinitionId is not provided) |
eventDefinitionId | int | No | ID of an existing event definition |
description | string | No | Event description override |
location | string | No | Event location override |
includeInTracking | bool | No | Include in tracking display |
sendEmail | bool | No | Send email notification |
eventDate | DateTime | No | Event date (defaults to current UTC time) |
customValues | object | No | Custom key-value pairs |
skipIfExists | bool | No | Skip if an event with the same event definition already exists on this order |
eventDefinitionValues | object | No | Values for auto-creating a new event definition |
YAML Structure
task: "OrderTrackingEvent/Create@1"
name: addTrackingEvent
inputs:
orderId: "{{ orderId }}"
organizationId: "{{ organizationId }}"
eventDefinitionName: "Picked Up"
description: "Package picked up from origin"
location: "Memphis, TN"
includeInTracking: true
sendEmail: false
Auto-Link to Commodities
By default, when a tracking event is added to an order, it is automatically linked to all first-level commodities of that order. First-level commodities are those where ContainerCommodityId is null (i.e., they are not nested inside a container commodity).
This behavior can be disabled per-organization using an OrganizationConfig with config name tms.trackingEvents:
{
"configName": "tms.trackingEvents",
"customValues": {
"autoLinkToCommodities": false
}
}
| Config Key | Type | Default | Description |
|---|---|---|---|
autoLinkToCommodities | bool | true | When true, tracking events added to an order are automatically linked to all first-level commodities |
This auto-link behavior also applies when tracking events are added via TrackingEvent/Import@1 and Order/Import@1 since they use the same underlying command.
Import Orders
Bulk import or upsert orders from a file (CSV/JSON/XLSX), a URL, or inline order data. Supports creating/updating orders with entities, commodities, charges, contacts, and tracking events in a single call.
Input Modes
The task supports three input modes (at least one must be provided):
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId | int | Yes | The organization to import orders into |
fileUrl | string | No | URL to a file (CSV/JSON/XLSX) to import |
fileType | string | No | File type override (Csv, Json, Xlsx). Auto-detected from URL if omitted. Required when using stream. |
stream | Stream | No | Direct stream input for file data |
orders | List | No | Array of order data objects to import directly |
options | object | No | Import configuration options |
Import Options
| Option | Type | Default | Description |
|---|---|---|---|
defaultDivisionId | int | - | Default division when not provided in order data |
orderMatchByFields | List<string> | ["orderId"] | Fields to match existing orders (e.g., ["orderNumber"], ["trackingNumber"]) |
orderEntityMatchByFields | List<string> | ["orderEntityId"] | Fields to match order entities. Supports nested fields like "contact.name" |
orderEntityContactMatchByFields | List<string> | ["contactId"] | Fields to match contacts within order entities |
billToContactMatchByFields | List<string> | - | Fields to match bill-to contacts (e.g., ["name"]) |
commodityMatchByFields | List<string> | - | Fields to match commodities |
commodityMatchByTrackingNumber | bool | false | Match commodities by tracking number instead of ID |
inventoryItemMatchByFields | List<string> | ["inventoryItemId"] | Fields to match inventory items |
inventoryItemCustomerContactMatchByFields | List<string> | ["contactId"] | Fields to match customer contacts within inventory items |
contactAddressMatchByFields | List<string> | - | Fields to match existing contact addresses within order entities (e.g., ["addressLine", "postalCode"]). If null or empty, matches by contactAddressId only when provided. |
tagMatchByFields | List<string> | - | Fields to match existing tags |
linkTrackingEventsToCommodities | bool | false | When true, imported tracking events are automatically linked to the order's first-level (non-container) commodities |
skipIfExists | bool | true | Skip tracking events that already exist (deduplication) |
createEventDefinitions | bool | true | Auto-create missing event definitions for tracking events |
eventDefinitionDefaults | object | null | Default values for auto-created event definitions |
trackingEventMatchByFields | List<string> | ["eventDefinitionName", "eventDate"] | Fields for tracking event deduplication |
matchByEventDefinition | List<string> | null | Match EventDefinitions by CustomValues fields instead of EventName |
Order Data Properties
Each order in the orders array is a dictionary with standard order fields plus optional nested data:
| Property | Type | Description |
|---|---|---|
orderNumber | string | Order number |
trackingNumber | string | Tracking number |
orderType | string/int | Order type (e.g., "ParcelShipment", "Order", or int value) |
orderStatusId | int | Order status ID |
divisionId | int | Division ID (falls back to defaultDivisionId) |
billToContact | object | Bill-to contact data with name, contactType, etc. |
commodities | List | Array of commodity objects |
trackingEvents | List | Array of tracking event objects (see TrackingEvent/Import@1 for event format) |
| ...other order fields | Any standard order field |
Output Result
{
"result": {
"success": true,
"added": 5,
"updated": 2,
"errors": [],
"totalProcessed": 7,
"hasErrors": false
}
}
Basic Import from Inline Data
task: "Order/Import@1"
name: importOrders
inputs:
orders:
- orderNumber: "ORD-001"
orderType: "Order"
trackingNumber: "1Z999AA10123456784"
options:
defaultDivisionId: 1
outputs:
- name: result
mapping: "result"
Import from File URL
task: "Order/Import@1"
name: importFromFile
inputs:
fileUrl: "{{ fileUrl }}"
fileType: "Json"
options:
defaultDivisionId: "{{ divisionId }}"
orderMatchByFields:
- "trackingNumber"
outputs:
- name: result
mapping: "result"
Import with Tracking Events
Orders can include embedded tracking events that are processed automatically during import. This uses the same tracking event import logic as TrackingEvent/Import@1.
task: "Order/Import@1"
name: importWithEvents
inputs:
orders:
- trackingNumber: "1Z999AA10123456784"
orderType: "ParcelShipment"
trackingEvents:
- eventDefinitionName: "Picked Up"
eventDate: "2025-01-15T10:30:00Z"
description: "Package picked up from origin"
location: "Memphis, TN"
- eventDefinitionName: "In Transit"
eventDate: "2025-01-15T14:00:00Z"
description: "Package in transit"
options:
defaultDivisionId: "{{ divisionId }}"
createEventDefinitions: true
skipIfExists: true
trackingEventMatchByFields:
- "eventDefinitionName"
- "eventDate"
outputs:
- name: result
mapping: "result"
Import with Bill-To Contact Matching
task: "Order/Import@1"
name: importWithContact
inputs:
orders:
- trackingNumber: "1Z999AA10123456784"
orderType: "ParcelShipment"
billToContact:
name: "Acme Corp"
contactType: "Customer"
options:
defaultDivisionId: "{{ divisionId }}"
billToContactMatchByFields:
- "name"
outputs:
- name: result
mapping: "result"
Behavior
- New orders: Created when no match is found using
orderMatchByFields - Existing orders: Updated when a match is found
- Contacts: Matched using configured match fields with Lucene filter queries scoped to organization. Cached per import session to prevent duplicates.
- Contact Addresses: Matched using
contactAddressMatchByFieldsscoped to organization and (when available) contact. Supports Lucene filter-based matching. Cached per import session. If no match is found, a new contact address is created. - Order Entities: The
contactandcontactAddressnested objects are processed separately from other entity fields — they are matched/created first, then linked to the order entity. Thecontactblock is optional — if omitted, the order entity is created without a contact relationship. - Tags: Shared cache for order and commodity tags within an import session.
- Tracking events: Processed after order creation/update. Duplicate events are skipped when
skipIfExistsis true - Event definitions: Auto-created when
createEventDefinitionsis true and the definition doesn't exist - Tracking Event → Commodity Linking: When
linkTrackingEventsToCommoditiesis enabled, each imported tracking event is linked to all immediate commodities on the order (i.e., commodities that are not nested inside a container commodity). This is useful for parcel and LTL shipments where tracking events apply to all pieces. - Errors: Individual order errors are collected in
result.errorswithout stopping the batch
Outputs
| Output | Description |
|---|---|
result | Import result containing created/updated orders and any errors |
result.order | The imported order (when single order) |
Example Order Workflow
workflow:
name: "Order / Create Order Example Workflow"
description: "Create Order Example Workflow"
version: "1.0"
executionMode: "Sync"
inputs:
- name: "billToContactId"
type: "Contact"
displayName: "Bill to contact id"
description: "Bill to contact id"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.billToContactId"
- name: "customValues"
type: "string,string"
displayName: "Custom values"
description: "Custom values"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.customValues"
- name: "divisionId"
type: "Division"
displayName: "Division id"
description: "Division id"
multiple: false
required: true
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.divisionId"
- name: "employeeContactId"
type: "Contact"
displayName: "Employee contact id"
description: "Employee contact id"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.employeeContactId"
- name: "entityTypeId"
type: "EntityType"
displayName: "Entity type id"
description: "Entity type id"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.entityTypeId"
- name: "equipmentTypeId"
type: "EquipmentType"
displayName: "Equipment type id"
description: "Equipment type id"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.equipmentTypeId"
- name: "lastOrderStatusModified"
type: "Date"
displayName: "Last order status modified"
description: "Last order status modified"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.lastOrderStatusModified"
- name: "orderNumber"
type: "string"
displayName: "Order number"
description: "Order number"
multiple: false
required: true
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.orderNumber"
- name: "orderStatusId"
type: "OrderStatus"
displayName: "Order status id"
description: "Order status id"
multiple: false
required: true
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.orderStatusId"
- name: "orderType"
type: "OrderTypes"
displayName: "Order type"
description: "Order type"
multiple: false
required: true
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.orderType"
- name: "salespersonContactId"
type: "Contact"
displayName: "Salesperson contact id"
description: "Salesperson contact id"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.salespersonContactId"
- name: "trackingNumber"
type: "string"
displayName: "Tracking number"
description: "Tracking number"
multiple: false
required: false
defaultValue: ""
additionalProperties:
visible: true
mapping: "order.trackingNumber"
outputs:
- name: order
mapping: "createOrderActivity.createOrder.order"
activities:
- name: "createOrderActivity"
description: "Create Order"
steps:
- task: "Order/Create@1"
name: createOrder
inputs:
order:
billToContactId: "{{ billToContactId }}"
customValues: "{{ customValues }}"
divisionId: "{{ divisionId }}"
employeeContactId: "{{ employeeContactId }}"
entityTypeId: "{{ entityTypeId }}"
equipmentTypeId: "{{ equipmentTypeId }}"
lastOrderStatusModified: "{{ lastOrderStatusModified }}"
orderNumber: "{{ orderNumber }}"
orderStatusId: "{{ orderStatusId }}"
orderType: "{{ orderType }}"
salespersonContactId: "{{ salespersonContactId }}"
trackingNumber: "{{ trackingNumber }}"
outputs:
- name: order
mapping: "order"
- name: "getOrderActivity"
description: "Get Order"
steps:
- task: "Order/Get@1"
name: getOrder
inputs:
orderId: "{{ createOrderActivity.createOrder.order.orderId }}"
outputs:
- name: orderFromGet
mapping: "order"
- name: "updateOrderActivity"
description: "Update Order"
steps:
- task: "Order/Update@1"
name: updateOrder
inputs:
orderId: "{{ getOrderActivity.getOrder.order.orderId }}"
order:
billToContactId: "{{ billToContactId }}"
customValues: "{{ customValues }}"
divisionId: "{{ divisionId }}"
employeeContactId: "{{ employeeContactId }}"
entityTypeId: "{{ entityTypeId }}"
equipmentTypeId: "{{ equipmentTypeId }}"
lastOrderStatusModified: "{{ lastOrderStatusModified }}"
orderNumber: "{{ orderNumber }}"
orderStatusId: "{{ orderStatusId }}"
orderType: "{{ orderType }}"
salespersonContactId: "{{ salespersonContactId }}"
trackingNumber: "{{ trackingNumber }}"
- name: "deleteOrderActivity"
description: "Delete Order"
steps:
- task: "Order/Delete@1"
name: deleteOrder
inputs:
orderId: "{{ getOrderActivity.getOrder.order.orderId }}"