> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telnesstech.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Order Fulfillment

> Automate provisioning and delivery of telecommunications services after order completion using Connect API workflows

Automate the complete order fulfillment process from order submission to service activation. This use case covers the workflows needed to provision telecommunications services, handle payments, and activate subscriptions for customers.

## Prerequisites

Before you begin, ensure you have:

* **Order Management**: Understanding of order creation and submission flows
* **Payment Processing**: Integration with payment collection systems
* **Service Provisioning**: Access to subscription and license management endpoints
* **Inventory Management**: Phone number inventory for mobile services

## Overview

Order fulfillment encompasses the complete process after order creation:

1. Submit orders for processing
2. Handle payment collection and validation
3. Provision services and create subscriptions
4. Activate services and manage inventory
5. Monitor fulfillment status and handle exceptions

## Step-by-Step Implementation

### Step 1: Submit Order for Fulfillment

Transform draft orders into submitted orders ready for processing:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // Submit an order for fulfillment
    const submitOrder = async (orderId) => {
      const submitResponse = await fetch(`https://connect.your-domain.com/api/v2/orders/${orderId}/submit`, {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      if (!submitResponse.ok) {
        const error = await submitResponse.json();
        throw new Error(`Order submission failed: ${error.message}`);
      }

      const submittedOrder = await submitResponse.json();
      console.log('Order submitted:', submittedOrder.orderId);

      return submittedOrder;
    };

    // Monitor order status after submission
    const monitorOrderStatus = async (orderId) => {
      const orderResponse = await fetch(`https://connect.your-domain.com/api/v2/orders/${orderId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      const order = await orderResponse.json();

      switch (order.state) {
        case 'SUBMITTED':
          console.log('Order submitted - awaiting processing');
          break;
        case 'PROCESSING':
          console.log('Order processing - services being provisioned');
          break;
        case 'COMPLETED':
          console.log('Order fulfilled - services active');
          break;
        case 'FAILED':
          console.error('Order fulfillment failed:', order.failureReason);
          break;
      }

      return order;
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Submit order for fulfillment
    curl -X POST "https://connect.your-domain.com/api/v2/orders/{orderId}/submit" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"

    # Monitor order status
    curl -X GET "https://connect.your-domain.com/api/v2/orders/{orderId}" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"
    ```
  </Tab>
</Tabs>

### Step 2: Handle Payment Collection

Create payment sessions to collect payment for orders:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // Create payment session for order
    const createPaymentSession = async (orderId) => {
      const paymentSessionData = {
        orderId: orderId,
        successUrl: 'https://yourstore.com/success',
        cancelUrl: 'https://yourstore.com/cancel',
        paymentMethods: ['card', 'bank_transfer'],
        metadata: {
          orderReference: orderId,
          channel: 'web'
        }
      };

      const sessionResponse = await fetch('https://connect.your-domain.com/api/v2/payment-sessions', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(paymentSessionData)
      });

      const paymentSession = await sessionResponse.json();

      // Redirect customer to payment URL
      console.log('Payment URL:', paymentSession.paymentUrl);

      return paymentSession;
    };

    // Check payment session status
    const checkPaymentStatus = async (paymentSessionId) => {
      const statusResponse = await fetch(`https://connect.your-domain.com/api/v2/payment-sessions/${paymentSessionId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      const session = await statusResponse.json();

      switch (session.status) {
        case 'pending':
          console.log('Payment pending - waiting for customer');
          break;
        case 'completed':
          console.log('Payment completed successfully');
          break;
        case 'failed':
          console.error('Payment failed:', session.failureReason);
          break;
        case 'cancelled':
          console.log('Payment cancelled by customer');
          break;
      }

      return session;
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Create payment session
    curl -X POST "https://connect.your-domain.com/api/v2/payment-sessions" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "orderId": "296af5b6-f3b3-4128-b307-5ddc9190502f",
        "successUrl": "https://yourstore.com/success",
        "cancelUrl": "https://yourstore.com/cancel",
        "paymentMethods": ["card", "bank_transfer"]
      }'

    # Check payment status
    curl -X GET "https://connect.your-domain.com/api/v2/payment-sessions/{paymentSessionId}" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"
    ```
  </Tab>
</Tabs>

### Step 3: Reserve Phone Numbers (For Mobile Services)

Reserve phone numbers from inventory before service activation:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // Lease phone numbers for mobile services
    const leasePhoneNumbers = async (requirements) => {
      const leaseData = {
        quantity: requirements.quantity,
        region: requirements.region,
        numberType: requirements.numberType || 'mobile',
        preferences: {
          areaCode: requirements.areaCode,
          pattern: requirements.pattern
        }
      };

      const leaseResponse = await fetch('https://connect.your-domain.com/api/v2/inventory/lease-numbers', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(leaseData)
      });

      const lease = await leaseResponse.json();

      console.log('Numbers leased:', lease.numbers.length);
      lease.numbers.forEach(number => {
        console.log('Reserved number:', number.number);
      });

      return lease;
    };

    // Example usage for mobile subscription
    const prepareMobileService = async (customer) => {
      const requirements = {
        quantity: 1,
        region: customer.region,
        areaCode: customer.preferredAreaCode
      };

      const numberLease = await leasePhoneNumbers(requirements);
      return numberLease.numbers[0]; // Use first available number
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Lease phone numbers
    curl -X POST "https://connect.your-domain.com/api/v2/inventory/lease-numbers" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "quantity": 1,
        "region": "SE",
        "numberType": "mobile",
        "preferences": {
          "areaCode": "08"
        }
      }'
    ```
  </Tab>
</Tabs>

### Step 4: Activate Subscriptions

Activate subscription services after successful payment:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // List subscriptions for an order
    const getOrderSubscriptions = async (orderId) => {
      const subscriptionsResponse = await fetch(`https://connect.your-domain.com/api/v2/subscriptions?orderId=${orderId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      const subscriptions = await subscriptionsResponse.json();
      return subscriptions.items;
    };

    // Activate a subscription
    const activateSubscription = async (subscriptionId) => {
      const activationData = {
        activationDate: new Date().toISOString(),
        notes: 'Activated via fulfillment process'
      };

      const activationResponse = await fetch(`https://connect.your-domain.com/api/v2/subscriptions/${subscriptionId}/activate`, {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(activationData)
      });

      if (!activationResponse.ok) {
        const error = await activationResponse.json();
        throw new Error(`Activation failed: ${error.message}`);
      }

      const activation = await activationResponse.json();
      console.log('Subscription activated:', subscriptionId);

      return activation;
    };

    // Complete fulfillment workflow
    const completeOrderFulfillment = async (orderId) => {
      // Get all subscriptions for the order
      const subscriptions = await getOrderSubscriptions(orderId);

      // Activate each subscription
      const activationPromises = subscriptions.map(sub => {
        if (sub.status === 'pending_activation') {
          return activateSubscription(sub.subscriptionId);
        }
        return Promise.resolve(sub);
      });

      const activatedSubscriptions = await Promise.all(activationPromises);

      console.log('Order fulfillment completed:', orderId);
      console.log('Active subscriptions:', activatedSubscriptions.length);

      return activatedSubscriptions;
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # List subscriptions for order
    curl -X GET "https://connect.your-domain.com/api/v2/subscriptions?orderId={orderId}" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"

    # Activate subscription
    curl -X POST "https://connect.your-domain.com/api/v2/subscriptions/{subscriptionId}/activate" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "activationDate": "2024-01-15T10:00:00Z"
      }'
    ```
  </Tab>
</Tabs>

## Error Handling and Retry Logic

Handle common fulfillment scenarios with proper error handling:

```javascript theme={null}
// Comprehensive error handling for fulfillment
const handleFulfillmentError = async (error, orderId, step) => {
  console.error(`Fulfillment error at step ${step}:`, error.message);

  const errorHandling = {
    'payment_failed': {
      action: 'retry_payment',
      message: 'Payment collection failed - customer needs to retry payment'
    },
    'inventory_unavailable': {
      action: 'wait_inventory',
      message: 'Phone numbers unavailable - waiting for inventory replenishment'
    },
    'activation_failed': {
      action: 'manual_review',
      message: 'Service activation failed - requires manual intervention'
    },
    'network_error': {
      action: 'retry_with_backoff',
      message: 'Network connectivity issue - will retry automatically'
    }
  };

  const handling = errorHandling[error.code] || {
    action: 'escalate',
    message: 'Unknown error - escalating to support'
  };

  // Log error for monitoring
  await logFulfillmentError(orderId, step, error, handling);

  // Take appropriate action
  switch (handling.action) {
    case 'retry_payment':
      return await createPaymentSession(orderId);
    case 'retry_with_backoff':
      return await retryWithBackoff(() => processStep(orderId, step));
    case 'manual_review':
      return await escalateToSupport(orderId, error);
    default:
      throw error;
  }
};

// Retry with exponential backoff
const retryWithBackoff = async (operation, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      if (attempt === maxRetries) throw error;

      const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
      console.log(`Retry attempt ${attempt} failed, waiting ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};
```

## Webhook Integration

Set up webhooks to handle asynchronous fulfillment events:

```javascript theme={null}
// Webhook handler for fulfillment events
const handleFulfillmentWebhook = (event) => {
  switch (event.type) {
    case 'order.submitted':
      console.log('Order submitted:', event.data.orderId);
      // Start fulfillment process
      return initiateFulfillment(event.data.orderId);

    case 'payment.completed':
      console.log('Payment completed:', event.data.paymentId);
      // Proceed with service activation
      return processServiceActivation(event.data.orderId);

    case 'subscription.activated':
      console.log('Subscription activated:', event.data.subscriptionId);
      // Send welcome notifications
      return sendActivationNotification(event.data);

    case 'fulfillment.completed':
      console.log('Fulfillment completed:', event.data.orderId);
      // Final cleanup and customer notification
      return completeFulfillmentNotification(event.data);

    case 'fulfillment.failed':
      console.error('Fulfillment failed:', event.data);
      // Handle fulfillment failure
      return handleFulfillmentFailure(event.data);

    default:
      console.log('Unknown webhook event:', event.type);
  }
};

// Express webhook endpoint example
app.post('/webhooks/connect', express.raw({type: 'application/json'}), (req, res) => {
  const event = JSON.parse(req.body);

  try {
    handleFulfillmentWebhook(event);
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook handling failed:', error);
    res.status(500).send('Internal Server Error');
  }
});
```

## Complete Fulfillment Workflow

Put it all together in a comprehensive fulfillment orchestrator:

```javascript theme={null}
// Complete fulfillment orchestrator
class OrderFulfillmentOrchestrator {
  async processOrder(orderId) {
    try {
      console.log(`Starting fulfillment for order: ${orderId}`);

      // Step 1: Submit order
      const submittedOrder = await this.submitOrder(orderId);

      // Step 2: Handle payment
      const paymentSession = await this.createPaymentSession(orderId);
      await this.waitForPaymentCompletion(paymentSession.paymentSessionId);

      // Step 3: Reserve resources
      const resources = await this.reserveResources(submittedOrder);

      // Step 4: Activate services
      const subscriptions = await this.activateServices(orderId);

      // Step 5: Complete fulfillment
      await this.completeFulfillment(orderId, subscriptions);

      console.log(`Fulfillment completed successfully for order: ${orderId}`);
      return { success: true, subscriptions };

    } catch (error) {
      console.error(`Fulfillment failed for order ${orderId}:`, error);
      await this.handleFulfillmentError(error, orderId);
      throw error;
    }
  }

  async waitForPaymentCompletion(paymentSessionId, timeout = 300000) {
    const startTime = Date.now();

    while (Date.now() - startTime < timeout) {
      const session = await this.checkPaymentStatus(paymentSessionId);

      if (session.status === 'completed') {
        return session;
      } else if (session.status === 'failed' || session.status === 'cancelled') {
        throw new Error(`Payment ${session.status}: ${session.failureReason}`);
      }

      // Poll every 5 seconds
      await new Promise(resolve => setTimeout(resolve, 5000));
    }

    throw new Error('Payment completion timeout');
  }

  async reserveResources(order) {
    const resources = {};

    // Reserve phone numbers for mobile services
    for (const lineItem of order.lineItems) {
      if (lineItem.productType === 'mobile') {
        const phoneNumber = await this.leasePhoneNumbers({
          quantity: 1,
          region: order.customer.region
        });
        resources[lineItem.lineItemId] = phoneNumber;
      }
    }

    return resources;
  }
}

// Usage example
const fulfillmentOrchestrator = new OrderFulfillmentOrchestrator();

// Process order fulfillment
fulfillmentOrchestrator.processOrder('296af5b6-f3b3-4128-b307-5ddc9190502fe4567-e89b-12d3-a456-426614174000')
  .then(result => console.log('Fulfillment successful:', result))
  .catch(error => console.error('Fulfillment failed:', error));
```

## Best Practices

### Fulfillment Monitoring

* Implement comprehensive logging for all fulfillment steps
* Set up alerts for failed fulfillments or unusual delays
* Track fulfillment metrics (completion time, success rate, failure reasons)
* Use correlation IDs to trace orders through the entire process

### Resource Management

* Reserve inventory (phone numbers) early in the process
* Implement inventory validation before order submission
* Handle inventory exhaustion gracefully with customer communication
* Clean up reserved resources if fulfillment fails

### Payment Handling

* Validate payment completion before service activation
* Implement payment retry mechanisms for failed transactions
* Handle partial payments appropriately
* Secure payment session data and comply with PCI standards

## Next Steps

After implementing order fulfillment:

<Card title="Customer self-service" icon="user" href="/developer-guide/use-cases/self-management">
  Enable customers to manage their active subscriptions and services
</Card>

<Card title="Payment processing" icon="credit-card" href="/developer-guide/use-cases/payment-processing">
  Set up recurring billing and ongoing payment management
</Card>

## Common Questions

**Q: How long does typical fulfillment take?**
A: Fulfillment times vary by service type. Mobile services typically activate within 15-30 minutes, while specialized services may take longer.

**Q: What happens if payment fails during fulfillment?**
A: The order remains in a pending state. Payment sessions can be retried, or new payment methods can be collected.

**Q: Can I customize the fulfillment workflow?**
A: Yes, you can implement custom fulfillment logic using webhooks and the various API endpoints to match your business requirements.
