.do
API Reference

ServiceOrder API Reference

Complete API reference for the ServiceOrder type, including order lifecycle management and payment processing

The $.ServiceOrder type represents a customer's purchase of a service. It tracks the complete order lifecycle from placement through completion, including payment processing, execution tracking, and delivery management.

Type Definition

// @errors: 7006
interface ServiceOrder extends Thing {
  $type: 'ServiceOrder'
  $id: string
  service: Service
  offering?: ServiceOffering
  customer: Person | Organization
  status: OrderStatus
  //        ^^^^^^^^^^^
  params: Record<string, any>
  pricing: OrderPricing
  //         ^^^^^^^^^^^^
  payment: PaymentInfo
  //         ^^^^^^^^^^^
  execution?: ServiceExecution
  deliverables?: Deliverable[]
  notes?: OrderNote[]
  priority?: OrderPriority
  dueDate?: string
  tags?: string[]
  metadata?: OrderMetadata
  customFields?: Record<string, any>
}

type OrderStatus =
  | 'pending'
  //  ^^^^^^^^^
  | 'confirmed'
  | 'processing'
  | 'completed'
  | 'cancelled'
  | 'failed'
  | 'refunded'

type OrderPriority = 'low' | 'normal' | 'high' | 'urgent'
//                   ^^^^^

interface OrderPricing {
  model: string
  amount: number
  currency: string
  discount?: number
  tax?: number
  total: number
  //^^^^^
}

interface PaymentInfo {
  paymentId?: string
  method: string
  status: PaymentStatus
  //        ^^^^^^^^^^^^^
  paidAt?: string
  refundedAt?: string
}

type PaymentStatus = 'pending' | 'processing' | 'paid' | 'failed' | 'refunded'

interface Deliverable {
  type: string
  description: string
  status: DeliverableStatus
  url?: string
  deliveredAt?: string
}

type DeliverableStatus = 'pending' | 'delivered' | 'approved'

interface OrderNote {
  author: string
  message: string
  timestamp: string
  visibility: 'internal' | 'customer'
  //            ^^^^^^^^^^
}

const order: ServiceOrder = {
  //    ^?
  $type: 'ServiceOrder',
  $id: 'order-123',
  service: {} as Service,
  customer: {} as Person,
  status: 'pending',
  params: {},
  pricing: {
    model: 'per-lead',
    amount: 500,
    currency: 'USD',
    total: 500,
  },
  payment: {
    method: 'card',
    status: 'pending',
  },
}

interface OrderMetadata {
  createdAt: string
  updatedAt: string
  confirmedAt?: string
  completedAt?: string
  cancelledAt?: string
  source?: string
  referrer?: string
  campaign?: string
}

Properties

Core Properties

service

  • Type: Service
  • Required: Yes
  • Description: The service being ordered
  • Pattern: $.ServiceOrder[id].service -> $.Service[serviceId]
  • Example: $.Service.get('service-123')

offering

  • Type: ServiceOffering
  • Required: No
  • Description: The marketplace offering (if purchased through marketplace)
  • Pattern: $.ServiceOrder[id].offering -> $.ServiceOffering[offeringId]

customer

  • Type: Person | Organization
  • Required: Yes
  • Description: The customer placing the order
  • Pattern: $.ServiceOrder[id].customer -> $.User[userId]
  • Example: $.User.current()

status

  • Type: OrderStatus
  • Required: Yes
  • Default: 'pending'
  • Values: 'pending' | 'confirmed' | 'processing' | 'completed' | 'cancelled' | 'failed' | 'refunded'
  • Description: Current status of the order

params

  • Type: Record<string, any>
  • Required: Yes
  • Description: Parameters and inputs for service execution
  • Example: { leads: [...], company_info: {...} }

Pricing Properties

pricing

  • Type: OrderPricing
  • Required: Yes
  • Description: Pricing details for this specific order
  • Properties:
    • model: Pricing model used
    • amount: Base amount
    • currency: ISO 4217 currency code
    • discount: Discount applied (optional)
    • tax: Tax amount (optional)
    • total: Final total amount

Payment Properties

payment

  • Type: PaymentInfo
  • Required: Yes
  • Description: Payment information and status
  • Properties:
    • paymentId: External payment ID
    • method: Payment method (e.g., 'card', 'bank', 'crypto')
    • status: Payment status
    • paidAt: Payment timestamp
    • refundedAt: Refund timestamp

Execution Properties

execution

  • Type: ServiceExecution
  • Required: No
  • Description: The execution instance for this order
  • Pattern: $.ServiceOrder[id].execution -> $.ServiceExecution[executionId]
  • Created: Automatically when order is confirmed

deliverables

  • Type: Deliverable[]
  • Required: No
  • Description: Expected or delivered outputs
  • Example: Reports, files, data exports, etc.

Optional Properties

notes

  • Type: OrderNote[]
  • Required: No
  • Description: Order notes and communications
  • Visibility: Can be internal or customer-visible

priority

  • Type: OrderPriority
  • Required: No
  • Default: 'normal'
  • Values: 'low' | 'normal' | 'high' | 'urgent'
  • Description: Order priority level

dueDate

  • Type: string
  • Required: No
  • Description: Expected completion date
  • Format: ISO 8601 timestamp

tags

  • Type: string[]
  • Required: No
  • Description: Tags for organization and filtering
  • Examples: ['rush', 'vip-customer', 'enterprise']

customFields

  • Type: Record<string, any>
  • Required: No
  • Description: Custom fields specific to service or provider
  • Example: { project_code: 'PROJ-123', department: 'Sales' }

Methods

create()

Create a new service order.

Signature:

$.ServiceOrder.create(config: OrderConfig): Promise<ServiceOrder>

Parameters:

  • config: Order configuration object

Returns: Promise resolving to the created ServiceOrder

Example:

const order = await $.ServiceOrder.create({
  service: $.Service.get('sdr-service'),
  offering: $.ServiceOffering.get('sdr-offering'),
  customer: $.User.current(),
  status: 'pending',
  params: {
    leads: [
      { name: 'John Doe', email: '[email protected]', company: 'Acme Inc' },
      { name: 'Jane Smith', email: '[email protected]', company: 'Beta Corp' },
    ],
    company_info: {
      name: 'Your Company',
      value_proposition: 'We automate sales processes',
    },
  },
  pricing: {
    model: 'per-lead',
    amount: 10,
    currency: 'USD',
    discount: 0,
    tax: 0,
    total: 10,
  },
  payment: {
    method: 'card',
    status: 'pending',
  },
  priority: 'normal',
})

get()

Retrieve an order by ID.

Signature:

$.ServiceOrder.get(id: string): Promise<ServiceOrder>

Parameters:

  • id: Order identifier

Returns: Promise resolving to the ServiceOrder

Example:

const order = await $.ServiceOrder.get('order-123')
console.log(order.status)
console.log(order.pricing)

list()

List all orders with optional filtering.

Signature:

$.ServiceOrder.list(filter?: OrderFilter): Promise<ServiceOrder[]>

Parameters:

  • filter: Optional filter criteria

Returns: Promise resolving to array of ServiceOrders

Example:

// List customer orders
const myOrders = await $.ServiceOrder.list({
  customer: $.User.current(),
})

// List pending orders
const pendingOrders = await $.ServiceOrder.list({
  status: 'pending',
})

find()

Find orders matching specific criteria.

Signature:

$.ServiceOrder.find(query: OrderQuery): Promise<ServiceOrder[]>

Parameters:

  • query: Query object with filter criteria

Returns: Promise resolving to matching ServiceOrders

Example:

// Find orders by status
const processingOrders = await $.ServiceOrder.find({
  status: 'processing',
})

// Find orders by service
const serviceOrders = await $.ServiceOrder.find({
  service: 'service-id',
})

// Find orders by date range
const recentOrders = await $.ServiceOrder.find({
  'metadata.createdAt': {
    $gte: startDate,
    $lte: endDate,
  },
})

update()

Update order properties.

Signature:

$.ServiceOrder[id].update(changes: Partial<OrderConfig>): Promise<ServiceOrder>

Parameters:

  • changes: Object containing properties to update

Returns: Promise resolving to updated ServiceOrder

Example:

// Update priority
await $.ServiceOrder[orderId].update({
  priority: 'high',
  tags: ['rush', 'vip'],
})

// Update due date
await $.ServiceOrder[orderId].update({
  dueDate: '2025-11-01T00:00:00Z',
})

confirm()

Confirm order and create execution.

Signature:

$.ServiceOrder[id].confirm(): Promise<ServiceOrder>

Returns: Promise resolving to confirmed ServiceOrder

Side Effects: Creates ServiceExecution automatically

Example:

const order = await $.ServiceOrder[orderId].confirm()
console.log(order.status) // 'confirmed'
console.log(order.execution) // ServiceExecution instance

process()

Start processing the order.

Signature:

$.ServiceOrder[id].process(): Promise<ServiceOrder>

Returns: Promise resolving to updated ServiceOrder

Example:

await $.ServiceOrder[orderId].process()
// Updates status to 'processing'

complete()

Mark order as completed.

Signature:

$.ServiceOrder[id].complete(result?: CompleteConfig): Promise<ServiceOrder>

Parameters:

  • result: Optional completion result with deliverables

Returns: Promise resolving to completed ServiceOrder

Example:

await $.ServiceOrder[orderId].complete({
  deliverables: [
    {
      type: 'report',
      description: 'Outreach campaign results',
      url: 'https://files.services.do/reports/abc123.pdf',
    },
  ],
})

cancel()

Cancel the order.

Signature:

$.ServiceOrder[id].cancel(config?: CancelConfig): Promise<ServiceOrder>

Parameters:

  • config: Optional cancellation configuration

Returns: Promise resolving to cancelled ServiceOrder

Example:

await $.ServiceOrder[orderId].cancel({
  reason: 'Customer request',
  refund: true,
})

delete()

Delete an order (soft delete).

Signature:

$.ServiceOrder[id].delete(): Promise<void>

Returns: Promise resolving when complete

Example:

await $.ServiceOrder[orderId].delete()

Property Access

ServiceOrders support semantic property access:

// Get order status
const status = await $.ServiceOrder[orderId].status

// Get customer
const customer = await $.ServiceOrder[orderId].customer

// Get service
const service = await $.ServiceOrder[orderId].service

// Get pricing
const pricing = await $.ServiceOrder[orderId].pricing

// Get payment info
const payment = await $.ServiceOrder[orderId].payment

// Get execution
const execution = await $.ServiceOrder[orderId].execution

// Get deliverables
const deliverables = await $.ServiceOrder[orderId].deliverables

Relations

service

Access the service being ordered.

Pattern: $.ServiceOrder[id].service -> $.Service[serviceId]

Example:

const order = await $.ServiceOrder.get('order-123')
const service = await order.service
console.log(service.name)

offering

Access the marketplace offering.

Pattern: $.ServiceOrder[id].offering -> $.ServiceOffering[offeringId]

Example:

const offering = await $.ServiceOrder[orderId].offering
console.log(offering.title)

customer

Access the customer who placed the order.

Pattern: $.ServiceOrder[id].customer -> $.User[customerId]

Example:

const customer = await $.ServiceOrder[orderId].customer
console.log(customer.name)

execution

Access the execution instance.

Pattern: $.ServiceOrder[id].execution -> $.ServiceExecution[executionId]

Example:

const execution = await $.ServiceOrder[orderId].execution
console.log(execution.status)
console.log(execution.progress)

provider

Access the service provider (from service).

Pattern: $.ServiceOrder[id].provider -> $.Organization | $.Person

Example:

const provider = await $.ServiceOrder[orderId].provider
console.log(provider.name)

invoice

Access the invoice for this order.

Pattern: $.ServiceOrder[id].invoice -> $.Invoice[invoiceId]

Example:

const invoice = await $.ServiceOrder[orderId].invoice
console.log(invoice.total)

Usage Examples

Example 1: Create SDR Outreach Order

const sdrOrder = await $.ServiceOrder.create({
  service: $.Service.get('sdr-service'),
  offering: $.ServiceOffering.get('sdr-offering'),
  customer: $.User.current(),
  status: 'pending',
  params: {
    leads: [
      {
        name: 'John Doe',
        email: '[email protected]',
        company: 'Acme Inc',
        title: 'VP Sales',
        linkedin: 'https://linkedin.com/in/johndoe',
      },
      {
        name: 'Jane Smith',
        email: '[email protected]',
        company: 'Beta Corp',
        title: 'CEO',
        linkedin: 'https://linkedin.com/in/janesmith',
      },
    ],
    company_info: {
      name: 'Your Company',
      value_proposition: 'We help B2B companies automate their sales process',
      website: 'https://yourcompany.com',
    },
    message_template: 'personalized',
    follow_up_sequence: 'standard',
  },
  pricing: {
    model: 'per-lead',
    amount: 10,
    currency: 'USD',
    discount: 0,
    tax: 0,
    total: 10,
  },
  payment: {
    method: 'card',
    status: 'pending',
  },
  priority: 'normal',
  dueDate: '2025-11-02T00:00:00Z',
  tags: ['new-customer', 'b2b'],
})

Example 2: Process Order Through Lifecycle

// Create order
const order = await $.ServiceOrder.create({
  service: $.Service.get('service-id'),
  customer: $.User.current(),
  params: {
    /* ... */
  },
  pricing: {
    /* ... */
  },
  payment: { method: 'card', status: 'pending' },
})

// Process payment
await $.ServiceOrder[order.$id].payment.process({
  method: 'card',
  token: 'tok_visa_4242',
})

// Confirm order (creates execution)
await $.ServiceOrder[order.$id].confirm()

// Start processing
await $.ServiceOrder[order.$id].process()

// Monitor execution
const execution = await $.ServiceOrder[order.$id].execution
const watcher = execution.watch()

watcher.on('completed', async (result) => {
  // Complete order with deliverables
  await $.ServiceOrder[order.$id].complete({
    deliverables: [
      {
        type: 'report',
        description: 'Campaign results',
        url: result.reportUrl,
      },
    ],
  })
})

Example 3: Add Order Notes

// Add internal note
await $.ServiceOrder[orderId].notes.add({
  author: $.User.current(),
  message: 'Customer requested rush delivery',
  visibility: 'internal',
})

// Add customer-visible note
await $.ServiceOrder[orderId].notes.add({
  author: $.User.current(),
  message: 'Your order is being processed and will be completed by tomorrow.',
  visibility: 'customer',
})

// Get all notes
const order = await $.ServiceOrder.get(orderId)
order.notes.forEach((note) => {
  console.log(`${note.author}: ${note.message}`)
})

Example 4: Handle Payment Processing

// Process payment
await $.ServiceOrder[orderId].payment.process({
  method: 'card',
  token: 'tok_visa_4242',
})

// Check payment status
const payment = await $.ServiceOrder[orderId].payment
console.log(`Payment status: ${payment.status}`)

// Issue refund
if (payment.status === 'paid') {
  await $.ServiceOrder[orderId].payment.refund({
    amount: payment.amount,
    reason: 'Customer request',
  })
}

Example 5: Query Orders with Filters

// Get customer's orders
const myOrders = await $.ServiceOrder.find({
  customer: $.User.current(),
})

// Get orders by status
const completedOrders = await $.ServiceOrder.find({
  status: 'completed',
  'metadata.completedAt': {
    $gte: '2025-10-01T00:00:00Z',
  },
})

// Get high-priority orders
const urgentOrders = await $.ServiceOrder.find({
  priority: { $in: ['high', 'urgent'] },
  status: { $nin: ['completed', 'cancelled'] },
})

Example 6: Content Writing Order

const contentOrder = await $.ServiceOrder.create({
  service: $.Service.get('content-service'),
  offering: $.ServiceOffering.get('blog-post-offering'),
  customer: $.User.current(),
  status: 'confirmed',
  params: {
    topic: 'AI in Sales Automation',
    keywords: ['ai sales', 'sales automation', 'sdr automation'],
    target_audience: 'B2B sales leaders',
    word_count: 1500,
    tone: 'professional but approachable',
    include_images: true,
  },
  pricing: {
    model: 'per-unit',
    amount: 50,
    currency: 'USD',
    discount: 0,
    tax: 0,
    total: 50,
  },
  payment: {
    paymentId: 'pi_abc123',
    method: 'card',
    status: 'paid',
    paidAt: '2025-10-26T10:30:00Z',
  },
  deliverables: [
    {
      type: 'blog-post',
      description: '1500-word blog post with images',
      status: 'pending',
    },
  ],
  priority: 'normal',
  dueDate: '2025-10-28T00:00:00Z',
})

Example 7: Enterprise Custom Order

const enterpriseOrder = await $.ServiceOrder.create({
  service: $.Service.get('custom-ai-service'),
  customer: $.Organization.get('enterprise-client'),
  status: 'confirmed',
  params: {
    project_type: 'custom-workflow',
    requirements: {
      steps: 10,
      integrations: ['salesforce', 'hubspot', 'slack'],
      users: 50,
      volume: 10000,
    },
    timeline: '6 weeks',
    support_level: 'premium',
  },
  pricing: {
    model: 'custom',
    amount: 50000,
    currency: 'USD',
    discount: 5000,
    tax: 4500,
    total: 49500,
  },
  payment: {
    method: 'invoice',
    status: 'pending',
    terms: 'net-30',
  },
  priority: 'high',
  dueDate: '2025-12-07T00:00:00Z',
  tags: ['enterprise', 'custom', 'premium-support'],
  customFields: {
    contract_number: 'ENT-2025-042',
    account_manager: '[email protected]',
    success_manager: '[email protected]',
  },
})

Example 8: Subscription Order

const subscriptionOrder = await $.ServiceOrder.create({
  service: $.Service.get('analytics-service'),
  offering: $.ServiceOffering.get('analytics-pro'),
  customer: $.User.current(),
  status: 'confirmed',
  params: {
    plan: 'professional',
    billing_period: 'monthly',
    users: 5,
    data_sources: ['database', 'api', 'csv'],
  },
  pricing: {
    model: 'subscription',
    amount: 299,
    currency: 'USD',
    period: 'monthly',
    discount: 0,
    tax: 29.9,
    total: 328.9,
  },
  payment: {
    paymentId: 'sub_xyz789',
    method: 'card',
    status: 'paid',
    paidAt: '2025-10-26T00:00:00Z',
    nextBillingDate: '2025-11-26T00:00:00Z',
  },
  priority: 'normal',
  tags: ['subscription', 'monthly'],
})

Example 9: Cancel Order with Refund

const order = await $.ServiceOrder.get('order-id')

// Cancel before processing
if (order.status === 'pending' || order.status === 'confirmed') {
  await $.ServiceOrder[order.$id].cancel({
    reason: 'Customer changed requirements',
    refund: true,
  })

  console.log('Order cancelled and refund processed')
}

Example 10: Get Order Statistics

// Get orders for a service
const service = await $.Service.get('service-id')
const orders = await service.orders

// Calculate statistics
const stats = {
  total: orders.length,
  completed: orders.filter((o) => o.status === 'completed').length,
  cancelled: orders.filter((o) => o.status === 'cancelled').length,
  pending: orders.filter((o) => o.status === 'pending').length,
  revenue: orders.filter((o) => o.status === 'completed').reduce((sum, o) => sum + o.pricing.total, 0),
}

console.log('Order Statistics:')
console.log(`- Total Orders: ${stats.total}`)
console.log(`- Completed: ${stats.completed}`)
console.log(`- Cancellation Rate: ${((stats.cancelled / stats.total) * 100).toFixed(1)}%`)
console.log(`- Total Revenue: $${stats.revenue.toFixed(2)}`)

Example 11: Batch Order Operations

// Get all pending orders
const pendingOrders = await $.ServiceOrder.find({
  status: 'pending',
  'payment.status': 'paid',
})

// Confirm all paid orders
await Promise.all(pendingOrders.map((order) => $.ServiceOrder[order.$id].confirm()))

console.log(`Confirmed ${pendingOrders.length} orders`)

Example 12: Order with Custom Deliverables

// Complete order with multiple deliverables
await $.ServiceOrder[orderId].complete({
  deliverables: [
    {
      type: 'report',
      description: 'Campaign performance report',
      url: 'https://files.services.do/reports/campaign-report.pdf',
      status: 'delivered',
    },
    {
      type: 'data',
      description: 'Raw campaign data (CSV)',
      url: 'https://files.services.do/data/campaign-data.csv',
      status: 'delivered',
    },
    {
      type: 'dashboard',
      description: 'Real-time analytics dashboard',
      url: 'https://dashboards.services.do/campaign-123',
      status: 'delivered',
    },
  ],
})

Order Status Lifecycle

Orders progress through these statuses:

  1. pending: Order created, payment pending
  2. confirmed: Payment confirmed, ready for execution
  3. processing: Service is being executed
  4. completed: Service execution completed successfully
  5. cancelled: Order cancelled before completion
  6. failed: Execution failed
  7. refunded: Payment refunded

Status Transitions:

// pending -> confirmed
await order.confirm()

// confirmed -> processing
await order.process()

// processing -> completed
await order.complete()

// any -> cancelled
await order.cancel()

Events

ServiceOrders emit the following events:

  • order.created - Order was created
  • order.confirmed - Order was confirmed
  • order.processing - Order started processing
  • order.completed - Order was completed
  • order.cancelled - Order was cancelled
  • order.failed - Order execution failed
  • order.payment.processed - Payment was processed
  • order.payment.failed - Payment failed
  • order.refunded - Order was refunded
  • order.note.added - Note was added

Example:

import { on } from 'sdk.do'

on.ServiceOrder.created(async (order) => {
  console.log(`New order: ${order.$id}`)
})

on.ServiceOrder.completed(async (order) => {
  console.log(`Order completed: ${order.$id}`)
  // Send customer notification
})

API Endpoints

ServiceOrders are accessible via REST API:

  • GET /api/orders - List orders
  • GET /api/orders/:id - Get order details
  • POST /api/orders - Create order
  • PUT /api/orders/:id - Update order
  • POST /api/orders/:id/confirm - Confirm order
  • POST /api/orders/:id/cancel - Cancel order
  • POST /api/orders/:id/complete - Complete order
  • GET /api/orders/:id/execution - Get execution
  • POST /api/orders/:id/notes - Add note
  • POST /api/orders/:id/payment - Process payment
  • POST /api/orders/:id/refund - Issue refund

Security

  • Customer Access: Customers can only view their own orders
  • Provider Access: Providers can view orders for their services
  • Admin Access: Admins can view all orders
  • Sensitive Data: Payment details are redacted in API responses

Schema.org Mapping

ServiceOrders extend Schema.org types:

Property Mappings:

  • orderNumber -> $id
  • customer -> customer
  • orderStatus -> status
  • orderDate -> metadata.createdAt
  • paymentMethod -> payment.method
  • orderDelivery -> deliverables

See Also