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

# Complete Shipping Workflow

> End-to-end guide for integrating cross-border shipping

This guide walks through the complete shipping workflow from order creation to delivery confirmation.

## Workflow Overview

```mermaid theme={null}
graph LR
    A[Create Order] --> B[Generate Label]
    B --> C[Submit Manifest]
    C --> D[Track Parcel]
    D --> E[Delivery Confirmation]
```

## Step 1: Create Orders

When a customer places an order, create a parcel in CrossBorderly:

```javascript theme={null}
async function createShipment(order) {
  const response = await fetch('https://api.crbtrack.com/api/v1/orders/create', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.CROSSBORDERLY_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      idempotencyKey: `order-${order.id}`,
      externalOrderId: order.id,
      sender: {
        fullName: 'Your Company Name',
        phone: '+1 305-555-0123',
        address: {
          line1: '1234 Warehouse St',
          city: 'Miami',
          state: 'FL',
          zipCode: '33101',
          country: 'US'
        }
      },
      receiver: {
        fullName: order.customer.name,
        phone: order.customer.phone,
        email: order.customer.email,
        nationalId: order.customer.nationalId,
        address: {
          line1: order.shippingAddress.line1,
          city: order.shippingAddress.city,
          province: order.shippingAddress.province,
          zipCode: order.shippingAddress.zipCode,
          country: order.shippingAddress.country
        }
      },
      parcelDetails: {
        weightLbs: order.totalWeight,
        declaredValue: order.totalValue
      },
      products: order.items.map(item => ({
        description: item.name,
        quantity: item.quantity,
        unitFobValue: item.price,
        sku: item.sku
      }))
    })
  });

  const data = await response.json();
  
  // Store the tracking number in your database
  await db.orders.update(order.id, {
    trackingNumber: data.parcel.trackingNumber,
    labelUrl: data.parcel.labelUrl
  });
  
  return data;
}
```

## Step 2: Print Labels

Download and print the shipping label:

```javascript theme={null}
async function downloadLabel(trackingNumber) {
  const response = await fetch(
    `https://api.crbtrack.com/api/v1/labels/${trackingNumber}/download`,
    {
      headers: { 'X-API-Key': process.env.CROSSBORDERLY_API_KEY }
    }
  );
  
  // For web: Create download link
  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  
  // For server: Save to file
  const buffer = await response.arrayBuffer();
  await fs.writeFile(`./labels/${trackingNumber}.pdf`, Buffer.from(buffer));
}
```

## Step 3: Submit Manifest

Once you have a batch of parcels ready to ship, submit them as a manifest:

```javascript theme={null}
async function submitShipmentManifest(shipment) {
  const parcels = await db.parcels.findByShipment(shipment.id);
  
  const response = await fetch('https://api.crbtrack.com/api/v1/manifests/submit', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.CROSSBORDERLY_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      idempotencyKey: `manifest-${shipment.id}`,
      awbNumber: shipment.awbNumber,
      flightNumber: shipment.flightNumber,
      flightDate: shipment.flightDate,
      originAirport: 'MIA',
      destinationAirport: shipment.destination,
      carrier: shipment.carrier,
      country: shipment.country,
      parcels: parcels.map(p => ({
        trackingNumber: p.trackingNumber,
        bagCode: p.bagCode
      }))
    })
  });

  const data = await response.json();
  
  if (data.notFound?.length > 0) {
    console.warn('Some parcels not found:', data.notFound);
  }
  
  return data;
}
```

## Step 4: Track Parcels

### Real-time via Webhooks (Recommended)

Configure webhooks to receive status updates automatically:

```javascript theme={null}
// Webhook endpoint
app.post('/webhooks/crossborderly', (req, res) => {
  const event = req.body;
  
  switch (event.event) {
    case 'parcel.status_changed':
      handleStatusChange(event.data);
      break;
    case 'parcel.delivered':
      handleDelivery(event.data);
      break;
    case 'parcel.exception':
      handleException(event.data);
      break;
  }
  
  res.status(200).send('OK');
});

async function handleStatusChange(data) {
  const order = await db.orders.findByTracking(data.trackingNumber);
  
  await db.orders.update(order.id, {
    shippingStatus: data.newStatus,
    lastUpdate: data.timestamp
  });
  
  // Notify customer
  await sendCustomerEmail(order.customer.email, {
    subject: 'Your order has been updated',
    status: data.newStatus,
    trackingUrl: `https://track.crbtrack.com/${data.trackingNumber}`
  });
}
```

### Polling (Fallback)

For batch status checks:

```javascript theme={null}
async function syncTrackingStatus(trackingNumbers) {
  const response = await fetch('https://api.crbtrack.com/api/v1/tracking/batch', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.CROSSBORDERLY_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ trackingNumbers, includeHistory: false })
  });

  const data = await response.json();
  
  for (const result of data.results) {
    await db.orders.update({ trackingNumber: result.trackingNumber }, {
      shippingStatus: result.status
    });
  }
}
```

## Step 5: Handle Exceptions

Build exception handling into your workflow:

```javascript theme={null}
async function handleShippingException(data) {
  const order = await db.orders.findByTracking(data.trackingNumber);
  
  switch (data.exceptionType) {
    case 'CUSTOMS_HOLD':
      // May need additional documentation
      await notifyOpsTeam(order, 'Customs hold - review required');
      break;
      
    case 'DELIVERY_FAILED':
      // Schedule retry or contact customer
      await scheduleDeliveryRetry(order);
      await sendDeliveryFailureEmail(order.customer.email);
      break;
      
    case 'ADDRESS_ISSUE':
      // Address correction needed
      await requestAddressCorrection(order);
      break;
      
    case 'RETURN_TO_SENDER':
      // Initiate refund process
      await initiateRefund(order);
      break;
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Batch Operations">
    * Create orders in batches during off-peak hours
    * Submit manifests when you have 50+ parcels ready
    * Use batch tracking instead of individual calls
  </Accordion>

  <Accordion title="Error Recovery">
    * Always use idempotency keys for POST requests
    * Implement retry logic with exponential backoff
    * Store raw API responses for troubleshooting
  </Accordion>

  <Accordion title="Performance">
    * Cache label URLs (valid for 24 hours)
    * Use webhooks instead of polling when possible
    * Parallelize non-dependent API calls
  </Accordion>
</AccordionGroup>

## Complete Integration Checklist

<Steps>
  <Step title="Account Setup">
    * [ ] Get production API key
    * [ ] Configure webhook URL
    * [ ] Set up sandbox for testing
  </Step>

  <Step title="Order Integration">
    * [ ] Map your order data to CrossBorderly format
    * [ ] Implement idempotency with order IDs
    * [ ] Handle validation errors
  </Step>

  <Step title="Label Management">
    * [ ] Auto-download labels on order creation
    * [ ] Implement reprint functionality
    * [ ] Handle label format preferences (PDF/ZPL)
  </Step>

  <Step title="Manifest Workflow">
    * [ ] Batch parcels by destination country
    * [ ] Submit manifests before carrier pickup
    * [ ] Handle partial success responses
  </Step>

  <Step title="Tracking">
    * [ ] Configure webhook endpoints
    * [ ] Map status codes to your system
    * [ ] Build customer tracking page
  </Step>

  <Step title="Exception Handling">
    * [ ] Monitor for delivery exceptions
    * [ ] Implement retry logic
    * [ ] Set up alerts for operations team
  </Step>
</Steps>
