Unified Order Service
Home
Getting Started
  • Core API
  • Drone API
Resources
Home
Getting Started
  • Core API
  • Drone API
Resources
  • Introduction

    • Getting Started
    • System Overview
    • Authentication
  • Core Concepts

    • Working with Orders
    • Working with Channels
    • Places
    • Storage Locations
    • Places Management Dashboard
  • Integration

    • Webhooks
    • Order Status Workflows
    • FCM Push Notifications
  • Advanced Topics

    • API Keys
    • Order Versioning
    • Picking App Integration Guide
    • Subscriptions
    • Cancellation Reasons

Order Status Workflows

The Unified Order Service (UOS) includes a comprehensive order status management system. This guide explains the available order statuses and the workflows for transitioning between them.

Order Statuses

Orders in the UOS system can have the following statuses:

StatusDescription
pendingInitial state when order is created
processingOrder is being processed
pickingOrder is being picked in the warehouse
pickedOrder has been picked and ready for delivery/collection
retrievingOrder is ready to be retrieved (intermediate state before final fulfillment)
shippedOrder has been shipped (Home Delivery)
collectedOrder has been collected by customer (Click & Collect)
completedOrder has been fulfilled
cancelledOrder has been cancelled
failedOrder processing failed
suspendedOrder is temporarily suspended

Status Transition Flow

The following diagram illustrates the typical flow of order statuses:

Home Delivery Flow

pending → processing → picking → picked → retrieving → shipped → completed

Click & Collect Flow

pending → processing → picking → picked → retrieving → collected → completed

Alternative/Direct Paths

picked → completed (direct completion without retrieving)

Status Exit Paths

  • Most statuses → cancelled (Order cancellation)
  • Most statuses → failed (Processing failure)
  • Most statuses → suspended (Temporary suspension)
  • failed → processing (Retry after failure)
  • completed → cancelled (Late cancellation)

Valid Status Transitions

The system enforces valid status transitions to maintain order integrity. Below are all allowed transitions from each status:

From StatusAllowed Next Statuses
pendingprocessing, cancelled, failed, suspended
processingpicking, cancelled, failed, suspended
pickingpicked, cancelled, failed, suspended
pickedretrieving, completed, cancelled, failed, suspended
retrievingshipped, collected, cancelled, failed, suspended
shippedcompleted, cancelled, failed, suspended
collectedcompleted, cancelled, failed, suspended
completedcancelled
cancelled(no transitions allowed - terminal state)
failedprocessing (allows retry)
suspendedpending, processing, picking, cancelled, failed

Invalid Transitions

Attempting to transition to a status not listed in the table above will result in a 422 Unprocessable Entity error. The system validates all status transitions to prevent invalid order states.

Automatic Sequential Transitions

The UOS system includes automatic sequential transition logic that handles certain multi-step status changes transparently. When a status update requires intermediate steps to maintain valid transition rules, the system automatically executes the required transitions in sequence.

How It Works

When you request a status change that would violate the valid transition rules, the system:

  1. Detects the invalid direct transition
  2. Calculates the required intermediate steps
  3. Executes each transition in sequence
  4. Returns success with indication of the auto-transition

All intermediate status changes are recorded in the order history and trigger appropriate webhook notifications.

Supported Auto-Transitions

The following auto-transitions are currently supported:

pending → picking

Direct Request: pending → picking
Actual Transitions: pending → processing → picking

When an order in pending status is updated to picking, the system automatically transitions through processing first.

picked → shipped

Direct Request: picked → shipped
Actual Transitions: picked → retrieving → shipped

Force Transitions

For advanced use cases where external systems need to bypass status transition validation (e.g., when syncing order statuses that have already progressed through intermediate steps), UOS supports the X-Force-Transition header.

When to Use Force Transitions

Force transitions are useful when:

  • External systems (like CC Platform) have already processed intermediate status steps internally
  • Bulk status updates need to sync final statuses without going through each intermediate step
  • Status reconciliation between external systems and UOS is required

How It Works

When you include X-Force-Transition: true in your request:

  1. Forward Transitions: Validation is bypassed, allowing transitions like picking → completed (skipping picked, retrieving, shipped)
  2. Backward Transitions: Always rejected with 403 Forbidden, even with the FORCE header
  3. Loop Prevention: Webhooks back to your system are automatically skipped when X-Command-Origin is set

Example: Force Transition Request

curl -X PATCH "https://api.uos.mandeville.digital/v1/orders/order-123/status" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Force-Transition: true" \
  -H "X-Command-Origin: cc-adapter" \
  -H "X-Correlation-Id: corr-2025-12-14-001" \
  -d '{
    "status": "completed",
    "metadata": {
      "source": "cc_platform",
      "updated_by": "naveo-enterprise-adapter",
      "reason": "Order completed in CC Platform scheduler"
    }
  }'

Forward vs Backward Transitions

Forward Transitions (Allowed with FORCE):

  • ✅ picking → completed
  • ✅ picked → completed
  • ✅ processing → completed
  • ✅ Any transition that moves forward in the workflow

Backward Transitions (Always Rejected):

  • ❌ completed → picking (403 Forbidden)
  • ❌ picked → processing (403 Forbidden)
  • ❌ Any transition that moves backward in the workflow

Webhook Behavior

When a forced transition occurs, webhooks include:

{
  "event": "order:status_changed",
  "caused_by": "cc-adapter",
  "correlation_id": "corr-2025-12-14-001",
  "data": {
    "old_status": "picking",
    "new_status": "completed",
    "metadata": {
      "forced_transition": true,
      "updated_by": "naveo-enterprise-adapter"
    }
  }
}

Loop Prevention: If X-Command-Origin: cc-adapter is set, webhooks to URLs containing "cc-adapter" are automatically skipped to prevent feedback loops.

Security Considerations

  • Forward-Only: Only forward transitions can bypass validation
  • Authentication: Existing authentication mechanisms apply
  • Audit Logging: All forced transitions are logged for security monitoring
  • Rate Limiting: Existing rate limits apply to forced transitions

When an order in picked status is updated to shipped, the system automatically transitions through retrieving first.

picking → retrieving (Courier Dispatch)

Direct Request: picking → retrieving
Behavior: Courier dispatch notification - metadata update + FCM notification, status stays picking

When a courier is dispatched during picking, this is handled as a notification event rather than a status change. The system updates courier metadata and sends an FCM notification to the picker app, but the order status remains picking.

Courier Dispatch Response

When a courier dispatch is received during picking, the API returns:

{
  "message": "Courier information updated",
  "orderId": "order-123",
  "status": "picking",
  "courier_dispatched": true,
  "courier_info": {
    "courier_status": "en_route",
    "dispatched_at": "2023-11-15T14:30:00Z",
    "driver_id": "DRV-123"
  }
}

The order status remains picking and an FCM notification is sent to the picker app.

Webhook Notifications

For courier dispatch during picking, an order:updated webhook is sent with courier metadata:

{
  "event_type": "order:updated",
  "event_id": "evt-001",
  "timestamp": "2023-11-15T14:30:00Z",
  "data": {
    "order_number": "ORD-001",
    "status": "picking",
    "metadata": {
      "courier_info": {
        "courier_status": "en_route",
        "dispatched_at": "2023-11-15T14:30:00Z"
      }
    }
  }
}

Order History

All auto-transition steps are recorded in the order history. You can view the complete transition path by querying the order's status history:

GET /v1/orders/{orderId}/status-history

Each transition includes metadata indicating whether it was an automatic transition:

{
  "history": [
    {
      "version": 5,
      "status": {
        "from": "picking",
        "to": "picked"
      },
      "metadata": {
        "auto_transition": true,
        "reason": "Auto-transition to enable retrieving status"
      },
      "timestamp": "2023-11-15T14:30:00Z"
    },
    {
      "version": 6,
      "status": {
        "from": "picked",
        "to": "retrieving"
      },
      "metadata": {
        "auto_transition_final": true
      },
      "timestamp": "2023-11-15T14:30:01Z"
    }
  ]
}

Use Cases

Auto-transitions are particularly useful in the following scenarios:

External System Integration: When external delivery management systems (such as logistics providers) send status updates without knowledge of all intermediate states required by UOS.

Simplified API Usage: Clients can request the final desired status without managing intermediate state transitions manually.

Workflow Consistency: Ensures all orders follow the same state transition paths regardless of the source system, maintaining data integrity and audit trails.

Important Considerations

  • Auto-transitions are atomic from the caller's perspective but execute as separate database transactions internally
  • Each intermediate status change generates its own webhook notification
  • All transitions are recorded in the order history for complete audit trails
  • Auto-transitions maintain all validation rules and do not bypass any security checks
  • Metadata provided in the original request is preserved and applied to the final status

Status-Specific Metadata

When updating an order's status, certain statuses require specific metadata:

Cancelled Status

When updating to the cancelled status, you must provide a cancellation reason:

{
  "status": "cancelled",
  "metadata": {
    "cancellation_reason": "customer_requested",
    "notes": "Customer changed their mind"
  }
}

Valid cancellation reasons:

  • customer_requested or customer_request: Cancelled by customer request
  • customer_service: Cancelled by customer service (CBS)
  • customer_no_show: Cancelled due to customer no-show (SOM)
  • out_of_stock: Cancelled due to items being out of stock
  • fraud_suspected: Cancelled due to suspected fraudulent activity

Picking Status

When updating to the picking status, you must provide a picker ID:

{
  "status": "picking",
  "metadata": {
    "picker_id": "PICKER123"
  }
}

Shipped Status

When updating to the shipped status, you can provide shipping information:

{
  "status": "shipped",
  "metadata": {
    "tracking_number": "TRACK123456",
    "carrier": "DHL",
    "shipping_method": "standard",
    "estimated_delivery": "2023-11-15T14:00:00Z",
    "packages": [
      {
        "id": "PKG001",
        "weight": "2.5kg",
        "dimensions": "30x20x15cm"
      }
    ]
  }
}

Retrieving Status

When updating to the retrieving status, the order is ready to be retrieved for final fulfillment (either shipping or customer collection):

{
  "status": "retrieving",
  "metadata": {
    "ready_at": "2023-11-15T12:00:00Z",
    "retrieval_location": "Dispatch Area 3",
    "prepared_by": "STAFF123"
  }
}

Collected Status

When updating to the collected status, you must provide information about who collected the order:

{
  "status": "collected",
  "metadata": {
    "collected_by": "John Smith",
    "collected_at": "2023-11-15T13:45:00Z",
    "id_verified": true,
    "verification_method": "photo_id"
  }
}

Suspended Status

When suspending an order, provide a reason:

{
  "status": "suspended",
  "metadata": {
    "suspension_reason": "payment_verification",
    "expected_resolution_date": "2023-11-16T12:00:00Z",
    "notes": "Waiting for payment verification"
  }
}

Status History

Every time an order's status changes, the system records:

  • The previous status
  • The new status
  • When the change occurred
  • Who or what initiated the change
  • Any associated metadata

This status history is accessible through the API at the /v1/orders/{orderId}/status-history endpoint.

Updating Order Status

Using the Core API

To update an order's status using the Core API, send a PATCH request to the /v1/orders/{orderId}/status endpoint:

curl -X PATCH "https://api.uos.mandeville.digital/v1/orders/order-123/status" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "processing",
    "metadata": {
      // Status-specific metadata if required
    }
  }'

Force Transition Header (Advanced)

For systems that need to bypass status transition validation (e.g., when syncing statuses that have already progressed through intermediate steps), you can use the X-Force-Transition header:

curl -X PATCH "https://api.uos.mandeville.digital/v1/orders/order-123/status" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Force-Transition: true" \
  -H "X-Command-Origin: your-system-name" \
  -H "X-Correlation-Id: corr-123456" \
  -d '{
    "status": "completed",
    "metadata": {
      "source": "your_system",
      "updated_by": "scheduler"
    }
  }'

Important Restrictions:

  • ✅ Only forward transitions can bypass validation (e.g., picking → completed)
  • ❌ Backward transitions are always rejected, even with the FORCE header (403 Forbidden)
  • 🔒 Include X-Command-Origin to prevent webhook loopbacks to your system

See Force Transitions section below for more details.

Response

The status update endpoint returns 202 Accepted when the status update is accepted. The response acknowledges receipt of the update request:

{
  "message": "Order status update in progress",
  "orderId": "order-123",
  "status": "processing",
  "forced_transition": false,
  "metadata": {
    "picker_id": "PICKER-123"
  }
}

When using X-Force-Transition: true, the response includes "forced_transition": true:

{
  "message": "Order status update in progress",
  "orderId": "order-123",
  "status": "completed",
  "forced_transition": true,
  "metadata": {
    "status_in_uos": "processing",
    "_internal_job_id": "job-abc123"
  }
}

Important: The 202 Accepted response indicates the status update has been accepted and queued for processing, not that it has been applied. You should wait for the webhook notification to confirm the status has actually changed.

Webhook Notifications

Status updates are processed asynchronously. To know when a status update has been successfully applied, subscribe to the order:status_changed webhook:

{
  "event_type": "order:status_changed",
  "event_id": "evt-123",
  "timestamp": "2023-11-15T14:30:00Z",
  "data": {
    "id": "order-123",
    "order_number": "ORD-001",
    "status": "processing",
    "previous_status": "pending",
    "metadata": {
      "picker_id": "PICKER-123"
    }
  }
}

Best Practice: Always rely on webhooks for confirmation of status changes, not the API response. This ensures your system has the most accurate and up-to-date order status.

Using the Drone API

To update an order's status using the Drone API, send a GET request to the /dts/drone/order/set_status endpoint:

curl -X GET "https://api.uos.mandeville.digital/dts/drone/order/set_status?orderId=order-123&status=3" \
  -H "Authorization: Bearer YOUR_API_KEY"

Picking App Scope Restrictions

The Drone API (picking app) has limited status control for system integrity. It can only set certain statuses:

Allowed Status Codes for Picking App:

  • 2: Picking (STATE_COLLECTING) - Start or continue picking process
  • 3: Picked (STATE_COLLECTED) - Complete picking process
  • 6: Cancelled (STATE_CANCELLED) - Cancel order during picking operations

Read-Only Status Codes for Picking App:

  • 1: Pending (STATE_OPEN) - Managed by order management systems
  • 4: Shipped (STATE_DELIVERING) - Managed by logistics/shipping systems
  • 5: Completed (STATE_DELIVERED) - Managed by delivery/collection systems

Valid Transitions for Picking App:

  • pending (1) → picking (2) Allowed
  • pending (1) → cancelled (6) Allowed
  • processing (1) → picking (2) Allowed
  • processing (1) → cancelled (6) Allowed
  • picking (2) → picked (3) Allowed
  • picking (2) → cancelled (6) Allowed
  • picked (3) → cancelled (6) Allowed

Forbidden Transitions for Picking App:

  • Any transition to shipped (4) or completed (5) Not Allowed
  • Any transition from shipped (4) or completed (5) Not Allowed
  • Direct pending/processing → picked (must go through picking) Not Allowed

Error Response Example:

{
  "responseType": "failure", 
  "status": 422,
  "message": {
    "error": "Picking app transition not allowed: Picking app cannot transition from 'picked' to 'shipped'",
    "data": {
      "current_status": "picked",
      "requested_status": "shipped", 
      "allowed_transitions": ["cancelled"],
      "error_code": "PICKING_APP_TRANSITION_NOT_ALLOWED"
    }
  }
}

Note that the Drone API uses numeric status codes that map to UOS string statuses with picking app scope restrictions enforced.

Special Status Operations

Marking an Order as Failed

Using the Drone API, you can mark an order as failed with an optional reason:

curl -X GET "https://api.uos.mandeville.digital/dts/drone/order/set_failed?orderId=order-123&reason=Out%20of%20stock" \
  -H "Authorization: Bearer YOUR_API_KEY"

Suspending an Order

You can temporarily suspend an order using the Drone API:

curl -X GET "https://api.uos.mandeville.digital/dts/drone/order/set_suspended?orderId=order-123&reason=Customer%20request" \
  -H "Authorization: Bearer YOUR_API_KEY"

To resume a suspended order:

curl -X GET "https://api.uos.mandeville.digital/dts/drone/order/unset_suspended?orderId=order-123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Real-Time Status Notifications

The UOS provides real-time status notifications through WebSockets. To subscribe to status changes:

  1. Connect to the WebSocket server at wss://api.uos.mandeville.digital/ws
  2. Send an authentication message with your API key
  3. Subscribe to the order status topic

Example WebSocket subscription:

// Example JavaScript WebSocket client
const socket = new WebSocket('wss://api.uos.mandeville.digital/ws');

socket.onopen = () => {
  // Authenticate
  socket.send(JSON.stringify({
    type: 'auth',
    apiKey: 'YOUR_API_KEY'
  }));
  
  // Subscribe to order status changes
  socket.send(JSON.stringify({
    type: 'subscribe',
    topic: 'orders.status',
    filter: {
      channel_id: 'channel-123'
    }
  }));
};

socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Order status changed:', data);
};

Best Practices

  • Only update an order to a valid next status in the workflow
  • Always provide required metadata for status changes
  • Use appropriate API endpoints based on your integration context
  • Monitor webhook and WebSocket notifications for status changes
  • Check order status history for troubleshooting
  • Handle status transitions asynchronously as they may take time to propagate through the system
Last Updated: 12/17/25, 7:04 AM
Prev
Webhooks
Next
FCM Push Notifications