Skip to content

DClient - Order Management

Client-side order and delivery management separate from map operations.

DClient Overview

DClient provides order management functionality independent of the map interface:

  • Create and manage delivery orders
  • Track packages and shipments
  • Manage waypoints and stops
  • Real-time event subscriptions
  • Customer and client operations

Works standalone or alongside MSI for complete delivery solutions.

Getting Started

typescript
import De from '@de./sdk'

// Initialize DClient
const dclient = new De.DClient({
  workspace: 'your-workspace-id',
  accessToken: 'your-access-token',
  env: 'prod'
})

// Create order
const order = await dclient.orders.create({
  type: 'delivery',
  customer: {
    name: 'John Doe',
    phone: '+1234567890'
  },
  pickup: {
    address: '123 Main St',
    coordinates: { lng: -74.0060, lat: 40.7128 }
  },
  delivery: {
    address: '456 Oak Ave',
    coordinates: { lng: -73.9855, lat: 40.7580 }
  }
})

console.log('Order created:', order.id)

Order Management

Creating Orders

1

Basic Order

Simple delivery order

typescript
const order = await dclient.orders.create({
  type: 'delivery',
  
  customer: {
    uid: 'user_123',        // Optional: existing user ID
    name: 'John Doe',
    phone: '+1234567890',
    email: '[email protected]'
  },
  
  pickup: {
    address: '123 Main St, New York, NY',
    coordinates: { lng: -74.0060, lat: 40.7128 },
    contactName: 'Store Manager',
    contactPhone: '+1234567891',
    instructions: 'Ring doorbell'
  },
  
  delivery: {
    address: '456 Oak Ave, New York, NY',
    coordinates: { lng: -73.9855, lat: 40.7580 },
    contactName: 'John Doe',
    contactPhone: '+1234567890',
    instructions: 'Leave at door',
    scheduledAt: '2024-03-15T14:30:00Z'
  },
  
  items: [
    {
      name: 'Package A',
      quantity: 1,
      weight: 2.5,
      value: 49.99
    }
  ],
  
  metadata: {
    orderNumber: 'ORD-12345',
    priority: 'standard'
  }
})

Order Types:

  • delivery - Standard delivery
  • pickup - Customer pickup
  • return - Return shipment
  • exchange - Exchange/swap
2

Multi-stop Order

Order with multiple waypoints

typescript
const order = await dclient.orders.create({
  type: 'delivery',
  
  customer: { /* ... */ },
  
  pickup: { /* ... */ },
  
  waypoints: [
    {
      type: 'pickup',
      address: '789 Pine Rd',
      coordinates: { lng: -73.9951, lat: 40.7489 },
      instructions: 'Second pickup location'
    },
    {
      type: 'delivery',
      address: '321 Elm St',
      coordinates: { lng: -73.9844, lat: 40.7614 },
      instructions: 'First drop-off'
    }
  ],
  
  delivery: { /* Final destination */ }
})

Retrieving Orders

1

Get Order by ID

Fetch specific order

typescript
const order = await dclient.orders.get('order_abc123')

console.log('Order status:', order.status)
console.log('Current location:', order.tracking?.currentLocation)
console.log('ETA:', order.tracking?.eta)
2

List Orders

Query orders with filters

typescript
const orders = await dclient.orders.list({
  status: 'in_transit',
  limit: 20,
  offset: 0,
  sortBy: 'createdAt',
  sortOrder: 'desc',
  customerId: 'user_123'
})

console.log('Active orders:', orders.data.length)
console.log('Total:', orders.total)

Filter Options:

typescript
{
  status?: 'pending' | 'assigned' | 'in_transit' | 'delivered' | 'cancelled'
  type?: 'delivery' | 'pickup' | 'return'
  customerId?: string
  agentId?: string
  startDate?: string
  endDate?: string
  limit?: number
  offset?: number
  sortBy?: 'createdAt' | 'updatedAt' | 'scheduledAt'
  sortOrder?: 'asc' | 'desc'
}

Updating Orders

typescript
// Update order details
await dclient.orders.update('order_abc123', {
  delivery: {
    ...existingDelivery,
    instructions: 'Updated: Call on arrival'
  },
  metadata: {
    ...existingMetadata,
    priority: 'urgent'
  }
})

// Update status
await dclient.orders.updateStatus('order_abc123', 'in_transit')

// Assign agent
await dclient.orders.assign('order_abc123', 'agent_xyz789')

Cancelling Orders

typescript
await dclient.orders.cancel('order_abc123', {
  reason: 'customer_request',
  notes: 'Customer changed plans'
})

Package Management

Adding Packages

1

Add Package to Order

Attach package details

typescript
const package = await dclient.packages.add('order_abc123', {
  trackingNumber: 'PKG-123456',
  weight: 5.0,
  dimensions: {
    length: 30,
    width: 20,
    height: 15
  },
  contents: 'Electronics',
  value: 299.99,
  fragile: true,
  requiresSignature: true
})

Tracking Packages

typescript
// Get package status
const package = await dclient.packages.get('pkg_abc123')

console.log('Status:', package.status)
console.log('Location:', package.currentLocation)
console.log('Last scan:', package.lastScan)

// Get package history
const history = await dclient.packages.getHistory('pkg_abc123')

history.forEach(event => {
  console.log(`${event.timestamp}: ${event.type} at ${event.location}`)
})

Waypoint Operations

Managing Waypoints

1

Add Waypoint

Add stop to existing order

typescript
const waypoint = await dclient.waypoints.add('order_abc123', {
  type: 'delivery',
  address: '999 Broadway',
  coordinates: { lng: -73.9712, lat: 40.7831 },
  contactName: 'Jane Smith',
  contactPhone: '+1234567892',
  instructions: 'Apartment 5B',
  order: 2  // Position in route
})
2

Update Waypoint

Modify waypoint details

typescript
await dclient.waypoints.update('waypoint_xyz', {
  status: 'completed',
  completedAt: new Date().toISOString(),
  notes: 'Successfully delivered'
})
3

Reorder Waypoints

Change waypoint sequence

typescript
await dclient.waypoints.reorder('order_abc123', [
  'waypoint_1',
  'waypoint_3',  // Swap order
  'waypoint_2'
])

Waypoint Status

typescript
// Complete waypoint
await dclient.waypoints.complete('waypoint_xyz', {
  completedAt: new Date().toISOString(),
  signature: signatureData,
  photo: photoData,
  notes: 'Delivered to resident'
})

// Skip waypoint
await dclient.waypoints.skip('waypoint_xyz', {
  reason: 'customer_unavailable',
  notes: 'No answer at door'
})

// Remove waypoint
await dclient.waypoints.remove('waypoint_xyz')

Order Services & Operators

Service Configuration

1

Configure Service Options

Set delivery service parameters

typescript
const order = await dclient.orders.create({
  // ... order details
  
  service: {
    type: 'express',           // 'standard' | 'express' | 'same_day'
    priority: 'high',          // 'low' | 'normal' | 'high'
    insuranceValue: 500,       // Insurance coverage
    requiresSignature: true,
    contactlessDelivery: false,
    ageVerification: false
  }
})

Operator Selection

typescript
// Assign to specific operator/LSP
await dclient.orders.assignOperator('order_abc123', {
  operatorId: 'lsp_xyz789',
  vehicleType: 'van',
  specialRequirements: ['refrigerated']
})

// Auto-assign based on rules
await dclient.orders.autoAssign('order_abc123', {
  preferredOperator: 'lsp_xyz789',
  maxDistance: 50,        // km from operator
  vehicleTypes: ['van', 'truck']
})

Order Lifecycle & Stages

Lifecycle Stages

typescript
// Order lifecycle
const lifecycle = {
  created: 'Order created',
  assigned: 'Agent assigned',
  accepted: 'Agent accepted',
  picking_up: 'Heading to pickup',
  picked_up: 'Package collected',
  in_transit: 'On the way to delivery',
  nearby: 'Arriving soon',
  delivered: 'Successfully delivered',
  cancelled: 'Order cancelled'
}

// Track stage transitions
dclient.on('order:stage_changed', (data) => {
  console.log(`Order ${data.orderId} moved to: ${data.stage}`)
  updateUI(data)
})

Intent Tokens & Routing

typescript
// Generate intent token for order tracking
const intent = await dclient.intents.create('order_abc123', {
  type: 'tracking',
  expiresIn: 86400,  // 24 hours
  permissions: ['view', 'location']
})

// Share tracking link
const trackingUrl = `https://track.example.com/${intent.token}`
sendToCustomer(trackingUrl)

// Validate and use intent
const order = await dclient.intents.resolve(intentToken)

Event System

Subscribing to Events

1

Order Events

Real-time order updates

typescript
// Subscribe to specific order
dclient.on('order:order_abc123', (update) => {
  console.log('Order updated:', update)
  
  switch(update.type) {
    case 'status_changed':
      updateOrderStatus(update.status)
      break
    case 'location_updated':
      updateMapMarker(update.location)
      break
    case 'eta_changed':
      updateETA(update.eta)
      break
  }
})
2

Global Events

All orders monitoring

typescript
// All order events
dclient.on('order:*', (event) => {
  console.log('Order event:', event.type, event.orderId)
})

// Specific event types
dclient.on('order:created', (order) => {
  notifyNewOrder(order)
})

dclient.on('order:delivered', (order) => {
  sendDeliveryNotification(order)
})

Event Filtering

typescript
// Filter events by criteria
dclient.events.filter({
  customerId: 'user_123',
  status: 'in_transit',
  types: ['location_updated', 'eta_changed']
}, (event) => {
  // Only receive filtered events
  handleEvent(event)
})

Unsubscribing

typescript
const handler = (order) => {
  console.log('Order updated:', order)
}

// Subscribe
dclient.on('order:abc123', handler)

// Unsubscribe
dclient.off('order:abc123', handler)

// Remove all listeners for order
dclient.removeAllListeners('order:abc123')

Client Operations

Customer Management

typescript
// Create customer profile
const customer = await dclient.customers.create({
  name: 'John Doe',
  phone: '+1234567890',
  email: '[email protected]',
  addresses: [
    {
      label: 'Home',
      address: '123 Main St',
      coordinates: { lng: -74.0060, lat: 40.7128 },
      default: true
    },
    {
      label: 'Work',
      address: '456 Office Blvd',
      coordinates: { lng: -73.9855, lat: 40.7580 }
    }
  ],
  preferences: {
    contactlessDelivery: true,
    notifications: {
      sms: true,
      email: true,
      push: false
    }
  }
})

// Update customer
await dclient.customers.update('customer_123', {
  preferences: {
    notifications: {
      sms: false,
      email: true,
      push: true
    }
  }
})

// Get customer orders
const customerOrders = await dclient.customers.getOrders('customer_123', {
  status: 'delivered',
  limit: 10
})

Preference Management

typescript
// Set delivery preferences
await dclient.preferences.set('customer_123', {
  deliveryWindow: {
    start: '09:00',
    end: '17:00'
  },
  preferredCarrier: 'lsp_xyz',
  contactlessDelivery: true,
  leaveAtDoor: true,
  safePlace: 'Front porch',
  specialInstructions: 'Ring doorbell twice'
})

// Get preferences
const prefs = await dclient.preferences.get('customer_123')

Complete Examples

E-commerce Checkout Integration

typescript
async function createDeliveryOrder(cartItems, deliveryAddress) {
  const dclient = new De.DClient({
    workspace: workspaceId,
    accessToken: token
  })
  
  // Create order from cart
  const order = await dclient.orders.create({
    type: 'delivery',
    
    customer: {
      uid: currentUser.id,
      name: currentUser.name,
      phone: currentUser.phone,
      email: currentUser.email
    },
    
    pickup: {
      address: warehouse.address,
      coordinates: warehouse.coordinates,
      contactName: 'Warehouse Manager',
      contactPhone: warehouse.phone
    },
    
    delivery: {
      address: deliveryAddress.formatted,
      coordinates: deliveryAddress.coordinates,
      contactName: currentUser.name,
      contactPhone: currentUser.phone,
      scheduledAt: selectedDeliverySlot,
      instructions: deliveryNotes
    },
    
    items: cartItems.map(item => ({
      name: item.name,
      quantity: item.quantity,
      weight: item.weight,
      value: item.price
    })),
    
    service: {
      type: deliverySpeed,  // 'express' or 'standard'
      insuranceValue: calculateInsurance(cartItems),
      requiresSignature: totalValue > 100
    },
    
    metadata: {
      cartId: cart.id,
      orderNumber: generateOrderNumber(),
      paymentId: payment.id
    }
  })
  
  // Track order
  trackOrder(order.id)
  
  return order
}

function trackOrder(orderId) {
  dclient.on(`order:${orderId}`, (update) => {
    switch(update.type) {
      case 'status_changed':
        updateOrderStatus(update.status)
        sendNotification(`Order ${update.status}`)
        break
        
      case 'agent_assigned':
        showDriverInfo(update.agent)
        break
        
      case 'location_updated':
        updateTrackingMap(update.location)
        break
        
      case 'eta_changed':
        updateDeliveryETA(update.eta)
        break
    }
  })
}

Delivery Driver App

typescript
class DriverApp {
  private dclient: any
  private currentOrders: Map<string, any> = new Map()
  
  async initialize(driverId: string) {
    this.dclient = new De.DClient({
      workspace: workspaceId,
      accessToken: driverToken
    })
    
    // Get assigned orders
    await this.loadOrders(driverId)
    
    // Subscribe to new assignments
    this.dclient.on('order:assigned', (order) => {
      if (order.agent.uid === driverId) {
        this.handleNewOrder(order)
      }
    })
  }
  
  async loadOrders(driverId: string) {
    const orders = await this.dclient.orders.list({
      agentId: driverId,
      status: ['assigned', 'in_transit'],
      sortBy: 'scheduledAt'
    })
    
    orders.data.forEach(order => {
      this.currentOrders.set(order.id, order)
    })
    
    this.updateRoute()
  }
  
  async acceptOrder(orderId: string) {
    await this.dclient.orders.updateStatus(orderId, 'accepted')
    
    const order = this.currentOrders.get(orderId)
    navigateToPickup(order.pickup.coordinates)
  }
  
  async completePickup(orderId: string) {
    await this.dclient.waypoints.complete(
      `${orderId}_pickup`,
      {
        completedAt: new Date().toISOString(),
        photo: await capturePhoto()
      }
    )
    
    await this.dclient.orders.updateStatus(orderId, 'picked_up')
    
    const order = this.currentOrders.get(orderId)
    navigateToDelivery(order.delivery.coordinates)
  }
  
  async completeDelivery(orderId: string) {
    const signature = await getSignature()
    const photo = await capturePhoto()
    
    await this.dclient.waypoints.complete(
      `${orderId}_delivery`,
      {
        completedAt: new Date().toISOString(),
        signature,
        photo,
        notes: deliveryNotes
      }
    )
    
    await this.dclient.orders.updateStatus(orderId, 'delivered')
    
    this.currentOrders.delete(orderId)
    showCompletionScreen()
  }
  
  private updateRoute() {
    const stops = Array.from(this.currentOrders.values())
      .flatMap(order => [order.pickup, order.delivery])
    
    optimizeRoute(stops)
  }
}

Type Definitions

typescript
interface Order {
  id: string
  type: 'delivery' | 'pickup' | 'return' | 'exchange'
  status: 'pending' | 'assigned' | 'in_transit' | 'delivered' | 'cancelled'
  
  customer: Customer
  pickup: Location
  delivery: Location
  waypoints?: Waypoint[]
  items: Item[]
  
  agent?: Agent
  
  tracking?: {
    currentLocation?: Coordinates
    eta?: string
    events: TrackingEvent[]
  }
  
  service?: ServiceOptions
  pricing?: Pricing
  metadata?: Record<string, any>
  
  createdAt: string
  updatedAt: string
}

interface Customer {
  uid?: string
  name: string
  phone: string
  email?: string
}

interface Location {
  address: string
  coordinates: Coordinates
  contactName?: string
  contactPhone?: string
  instructions?: string
  scheduledAt?: string
}

interface Item {
  name: string
  quantity: number
  weight?: number
  dimensions?: Dimensions
  value?: number
}

Best Practices

Do

  • Validate data before creating orders
  • Handle event subscriptions properly
  • Clean up listeners when done
  • Use metadata for custom fields
  • Implement retry logic for API calls
  • Cache frequently accessed data

Avoid

  • Creating duplicate orders
  • Storing sensitive data in metadata
  • Ignoring error responses
  • Over-polling for updates
  • Hardcoding credentials
  • Leaking event listeners

Next Steps