TypeScript SDK for DPD Local shipping API integration - database-agnostic and framework-independent
npm install @jazzdev/dpd-local-sdk> TypeScript SDK for integrating DPD Local shipping services into your application. Database-agnostic, framework-independent, and production-ready.



✅ Complete DPD Integration
- Create shipments and generate labels
- Address validation (UK postcodes)
- Real-time tracking
- Multi-parcel support
- Service selection (Next Day, By 12 PM)
✅ Database-Agnostic
- Works with any database (Firestore, MongoDB, PostgreSQL, etc.)
- Adapter pattern for easy integration
- TypeScript-first design
✅ Production-Ready
- Battle-tested in production
- Comprehensive error handling
- Automatic token management
- Request retry logic
- Detailed logging
✅ Developer-Friendly
- Full TypeScript support
- Comprehensive JSDoc comments
- Example implementations included
- Zero runtime dependencies (peer deps only)
``bash`
npm install @jazzdev/dpd-local-sdkor
yarn add @jazzdev/dpd-local-sdkor
pnpm add @jazzdev/dpd-local-sdk
`typescript
import { createDPDConfig } from '@jazzdev/dpd-local-sdk';
const config = createDPDConfig({
credentials: {
accountNumber: process.env.DPD_ACCOUNT_NUMBER!,
username: process.env.DPD_USERNAME!,
password: process.env.DPD_PASSWORD!,
},
business: {
name: 'Your Business Name',
collectionAddress: {
organisation: 'Your Company Ltd',
property: 'Unit 1',
street: '123 Main Street',
locality: '',
town: 'London',
county: 'Greater London',
postcode: 'SW1A 1AA',
countryCode: 'GB',
},
contactName: 'Your Name',
contactPhone: '+441234567890',
contactEmail: 'shipping@yourcompany.com',
},
});
`
The SDK requires two adapters to work with your database and storage:
#### Database Adapter
`typescript
import { DatabaseAdapter } from '@jazzdev/dpd-local-sdk';
const myDatabaseAdapter: DatabaseAdapter = {
async getOrder(orderId: string) {
// Your implementation
return await db.orders.findById(orderId);
},
async updateOrder(orderId: string, data: any) {
// Your implementation
await db.orders.update(orderId, data);
},
async getSavedAddresses(userId: string) {
// Your implementation
return await db.addresses.find({ userId });
},
async getSavedAddress(addressId: string) {
// Your implementation
return await db.addresses.findById(addressId);
},
async createSavedAddress(address) {
// Your implementation
const result = await db.addresses.create(address);
return result.id;
},
async updateSavedAddress(addressId: string, data) {
// Your implementation
await db.addresses.update(addressId, data);
},
async deleteSavedAddress(addressId: string) {
// Your implementation
await db.addresses.delete(addressId);
},
async createDPDLog(log) {
// Your implementation
const result = await db.dpdLogs.create(log);
return result.id;
},
async getDPDLogs(filters) {
// Your implementation
return await db.dpdLogs.find(filters);
},
};
`
#### Storage Adapter
`typescript
import { StorageAdapter } from '@jazzdev/dpd-local-sdk';
const myStorageAdapter: StorageAdapter = {
async uploadLabel(labelData: string, fileName: string) {
// Upload to your storage (S3, Firebase Storage, etc.)
const url = await storage.upload(labelData, labels/${fileName});
return url;
},
async getLabel(fileName: string) {
// Get label URL from storage
return await storage.getUrl(labels/${fileName});
},
async deleteLabel(fileName: string) {
// Delete label from storage
await storage.delete(labels/${fileName});`
},
};
`typescript
import { createCompleteShipment } from '@jazzdev/dpd-local-sdk';
const result = await createCompleteShipment(
'ORDER123', // Your order ID
{
orderRef: 'ORDER123',
service: '12', // Next Day Delivery
deliveryAddress: {
id: 'addr_123',
userId: 'user_123',
isDefault: true,
property: '10',
street: 'Downing Street',
town: 'London',
postcode: 'SW1A 2AA',
countryCode: 'GB',
contactName: 'John Doe',
contactPhone: '+441234567890',
validated: true,
createdAt: new Date(),
updatedAt: new Date(),
},
totalWeight: 2.5, // kg
numberOfParcels: 1,
customerEmail: 'customer@example.com',
customerPhone: '+441234567890',
deliveryInstructions: 'Leave with neighbor if not home',
collectionDate: '2024-01-15',
},
config,
myDatabaseAdapter,
myStorageAdapter
);
if (result.success) {
console.log('Shipment created!');
console.log('Shipment ID:', result.shipmentId); // Save this for label regeneration
console.log('Consignment Number:', result.consignmentNumber); // 10-digit reference
console.log('Parcel Number:', result.parcelNumber); // 14-digit tracking number
console.log('Tracking URL:', result.trackingUrl);
console.log('Label URL:', result.labelUrl);
} else {
console.error('Failed:', result.error);
}
`
When you create a shipment with DPD, you receive three different identifiers:
1. shipmentId - DPD's internal shipment identifier (numeric)
- Required for label regeneration
- Save this in your database!
2. consignmentNumber - 10-digit reference number (e.g., 6504286395)
- Used for internal tracking
3. parcelNumber - 14-digit tracking number (e.g., 15976504286395)
- What customers use to track their delivery
- Used in the tracking URL
`typescript
// When creating a shipment, save ALL identifiers:
const result = await createCompleteShipment(...);
if (result.success) {
await saveToDatabase({
shipmentId: result.shipmentId, // Save for label regeneration
consignmentNumber: result.consignmentNumber,
parcelNumber: result.parcelNumber, // Give to customer for tracking
trackingUrl: result.trackingUrl,
});
}
`
If you need to regenerate a label (e.g., printer jam), use the shipmentId:
`typescript
import { generateLabel } from '@jazzdev/dpd-local-sdk';
const result = await generateLabel(credentials, {
shipmentId: '12345678', // Use the shipmentId, not consignment/parcel number
labelFormat: 'zpl' // or 'clp', 'html'
});
`
A test script is included to verify label generation:
`bashUsing npm script
npm run test:label
The script will:
- Validate your DPD credentials
- Generate the label in the specified format
- Save it to a file (
label-)
- Display a preview of the label contentAPI Reference
$3
####
createDPDConfig(options)Creates a complete DPD module configuration.
Parameters:
-
options.credentials - DPD API credentials
- options.business - Your business information
- options.pricing (optional) - Custom pricing configuration
- options.services (optional) - Service configuration
- options.labels (optional) - Label printer configuration
- options.notifications (optional) - Email/SMS configuration
- options.testMode (optional) - Enable test modeReturns:
DPDModuleConfig$3
####
createCompleteShipment(orderId, params, config, dbAdapter, storageAdapter)Create a complete shipment including label generation and database update.
Parameters:
-
orderId - Your internal order ID
- params - Shipment parameters (address, weight, service, etc.)
- config - DPD configuration
- dbAdapter - Database adapter
- storageAdapter - Storage adapterReturns:
Promise####
validateDeliveryAddress(params, credentials)Validate a UK delivery address using postcodes.io API.
Parameters:
-
params.postcode - UK postcode
- params.town - Town/city name
- credentials - DPD credentialsReturns:
Promise####
testDPDConnection(credentials)Test connection to DPD API.
Parameters:
-
credentials - DPD credentialsReturns:
Promise<{ success: boolean; message: string }>$3
####
calculateDeliveryFee(subtotal, service, config)Calculate customer-facing delivery fee.
####
calculateDPDCost(weight, service, config)Calculate DPD shipping cost (what DPD charges you).
####
getNextCollectionDate()Get next available collection date (excludes Sundays).
####
getEstimatedDeliveryDate(service, collectionDate?)Calculate estimated delivery date.
####
getTrackingUrl(parcelNumber)Generate DPD tracking URL.
Integration Examples
$3
`typescript
// app/api/shipping/create/route.ts
import { createCompleteShipment } from '@jazzdev/dpd-local-sdk';
import { NextRequest, NextResponse } from 'next/server';export async function POST(req: NextRequest) {
const { orderId, deliveryAddress, weight } = await req.json();
const result = await createCompleteShipment(
orderId,
{
orderRef: orderId,
service: '12',
deliveryAddress,
totalWeight: weight,
numberOfParcels: 1,
customerEmail: deliveryAddress.contactEmail,
collectionDate: new Date().toISOString().split('T')[0],
},
dpdConfig,
databaseAdapter,
storageAdapter
);
return NextResponse.json(result);
}
`$3
`typescript
import express from 'express';
import { createCompleteShipment } from '@jazzdev/dpd-local-sdk';const app = express();
app.post('/api/shipping/create', async (req, res) => {
const { orderId, deliveryAddress, weight } = req.body;
const result = await createCompleteShipment(
orderId,
{
orderRef: orderId,
service: '12',
deliveryAddress,
totalWeight: weight,
numberOfParcels: 1,
customerEmail: deliveryAddress.contactEmail,
collectionDate: new Date().toISOString().split('T')[0],
},
dpdConfig,
databaseAdapter,
storageAdapter
);
res.json(result);
});
`Configuration
The SDK requires DPD credentials which you pass directly to the configuration:
`typescript
const config = createDPDConfig({
credentials: {
accountNumber: 'YOUR_ACCOUNT_NUMBER',
username: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
},
business: {
// Your business details
}
});
`Important: Credentials are passed programmatically - the SDK itself doesn't read from environment variables. How you store and retrieve credentials in your application is up to you.
Adapter Examples
Complete adapter examples are available in the
examples/ directory:-
examples/basic-usage.ts - Complete workflow example
- examples/regenerate-label.ts - Label regeneration example
- examples/firestore-adapter.ts - Firestore database adapter
- examples/firebase-storage-adapter.ts - Firebase Storage adapterFor other databases (MongoDB, PostgreSQL, etc.), implement the
DatabaseAdapter interface following the Firestore example as a reference. The adapter pattern is database-agnostic by design.Error Handling
`typescript
const result = await createCompleteShipment(...);if (!result.success) {
console.error("Error Code:", result.errorCode);
console.error("Error Message:", result.error);
// Handle specific errors
switch (result.errorCode) {
case "AUTH_FAILED":
// Invalid credentials
break;
case "INVALID_ADDRESS":
// Address validation failed
break;
case "NETWORK_ERROR":
// Connection issues
break;
default:
// Generic error
}
}
`TypeScript Support
This SDK is written in TypeScript and provides complete type definitions:
`typescript
import type {
DPDModuleConfig,
CreateShipmentParams,
CreateShipmentResult,
SavedAddress,
ShippingData,
DatabaseAdapter,
StorageAdapter,
} from '@jazzdev/dpd-local-sdk';
``Contributions are welcome! Please open an issue or submit a pull request on GitHub.
MIT © Taiow Babarinde
- 📧 Email: babsman4all@gmail.com
- 🐛 Issues: GitHub Issues
See CHANGELOG.md for release history.