Skip to main content

Installation

npm install @crossborderly/api-client

Quick Start

import { CrossBorderly } from '@crossborderly/api-client';

const client = new CrossBorderly({
  apiKey: process.env.CROSSBORDERLY_API_KEY,
  environment: 'production' // or 'sandbox'
});

// Create an order
const order = await client.orders.create({
  idempotencyKey: 'my-order-123',
  sender: { /* ... */ },
  receiver: { /* ... */ },
  parcelDetails: { /* ... */ }
});

console.log('Tracking:', order.parcel.trackingNumber);

Configuration

const client = new CrossBorderly({
  apiKey: 'pk_your_api_key',
  environment: 'production', // 'production' | 'sandbox'
  timeout: 30000, // Request timeout in ms
  maxRetries: 3, // Automatic retry count
  debug: false // Enable debug logging
});

Orders

Create Order

const order = await client.orders.create({
  idempotencyKey: `order-${Date.now()}`,
  sender: {
    fullName: 'John Smith',
    phone: '+1 305-555-0123',
    address: {
      line1: '1234 Main St',
      city: 'Miami',
      state: 'FL',
      zipCode: '33101',
      country: 'US'
    }
  },
  receiver: {
    fullName: 'María García',
    phone: '+593 99 123 4567',
    nationalId: '1234567890',
    address: {
      line1: 'Av. 9 de Octubre 123',
      city: 'Guayaquil',
      province: 'Guayas',
      zipCode: '090101',
      country: 'EC'
    }
  },
  parcelDetails: {
    weightLbs: 2.5,
    declaredValue: 99.99
  }
});

console.log(order.parcel.trackingNumber);
console.log(order.parcel.labelUrl);

Void Order

const result = await client.orders.void({
  idempotencyKey: 'void-123',
  trackingNumbers: ['CBECUSD123456789'],
  reason: 'Customer cancelled'
});

console.log('Voided:', result.voided);

Manifests

Submit Manifest

const manifest = await client.manifests.submit({
  idempotencyKey: 'manifest-123',
  awbNumber: '180-12345678',
  flightNumber: 'LA2480',
  flightDate: '2024-12-25',
  originAirport: 'MIA',
  destinationAirport: 'UIO',
  carrier: 'LATAM Airlines',
  country: 'EC',
  parcels: [
    { trackingNumber: 'CBECUSD123456789' },
    { trackingNumber: 'CBECUSD123456790' }
  ]
});

console.log('Linked:', manifest.linked);

Tracking

Single Parcel

const tracking = await client.tracking.get('CBECUSD123456789', {
  includeHistory: true
});

console.log('Status:', tracking.status);
for (const event of tracking.history) {
  console.log(`${event.timestamp}: ${event.statusName}`);
}

Batch Tracking

const results = await client.tracking.batch({
  trackingNumbers: ['CBECUSD123456789', 'CBECUSD123456790'],
  includeHistory: false
});

for (const parcel of results.results) {
  console.log(`${parcel.trackingNumber}: ${parcel.status}`);
}

Labels

Download Label

// Get label URL
const label = await client.labels.get('CBECUSD123456789');
console.log('Download:', label.labelUrl);

// Download as buffer
const buffer = await client.labels.download('CBECUSD123456789', {
  format: 'PDF'
});
await fs.writeFile('label.pdf', buffer);

Reprint Label

const reprint = await client.labels.reprint('CBECUSD123456789', {
  idempotencyKey: 'reprint-123',
  labelFormat: 'PDF'
});

console.log('New URL:', reprint.labelUrl);

Webhooks

Verify Webhook Signature

import { verifyWebhookSignature } from '@crossborderly/api-client';

app.post('/webhooks', (req, res) => {
  const isValid = verifyWebhookSignature(
    req.body,
    req.headers['x-crossborderly-signature'],
    process.env.WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook...
  res.status(200).send('OK');
});

Error Handling

import { CrossBorderlyError, ValidationError, RateLimitError } from '@crossborderly/api-client';

try {
  await client.orders.create({ /* ... */ });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log('Validation failed:', error.errors);
  } else if (error instanceof RateLimitError) {
    console.log('Rate limited, retry after:', error.retryAfter);
  } else if (error instanceof CrossBorderlyError) {
    console.log('API error:', error.code, error.message);
  }
}

TypeScript

The SDK includes full TypeScript definitions:
import { 
  CrossBorderly, 
  CreateOrderRequest, 
  CreateOrderResponse,
  ParcelStatus 
} from '@crossborderly/api-client';

const request: CreateOrderRequest = {
  idempotencyKey: 'order-123',
  sender: { /* ... */ },
  receiver: { /* ... */ },
  parcelDetails: { /* ... */ }
};

const response: CreateOrderResponse = await client.orders.create(request);