Secure Printing
Send shipping labels directly to printers without exposing PII to your WMS
Secure Printing
Data Border's Print API completes the secure label workflow. After generating a label via the Label Proxy, use the Print API to send the unredacted label directly to a printer—bypassing your WMS entirely.
The Complete Flow
sequenceDiagram
participant WMS
participant ADB
participant S3 as S3 Storage
participant DeviceHub as Device Hub
participant Printer
Note over WMS: Step 1: Generate label
WMS->>ADB: POST /api/label-proxy/forward
ADB->>WMS: {shipment_id, documents: [{uuid}]}
Note over WMS: Step 2: Request print
WMS->>ADB: POST /api/print/send<br/>{shipment_id, label_uuids}
ADB->>ADB: Lookup shipment
ADB->>S3: Fetch unredacted labels
S3->>ADB: Return label PDFs
ADB->>DeviceHub: POST print job
DeviceHub->>Printer: Print label
Printer->>DeviceHub: Acknowledge
DeviceHub->>ADB: Job complete
ADB->>ADB: Increment print count
ADB->>WMS: {status: "sent", is_reprint: false}Notice that your WMS never touches the actual label file—it only references it by UUID.
Setting Up Device Hub
Device Hub is a local print server that runs in your warehouse. Data Border sends print jobs to it over HTTPS.
For detailed installation and setup instructions, see the Device Hub documentation. You can also download the Device Hub client applications from devices.shipstream.io/downloads.
Device Hub Configuration
Each tenant in Data Border can have a Device Hub URL configured:
Tenant Configuration:
- deviceHubHost: https://devicehub.warehouse.local:8443
Contact your Data Border administrator to configure your Device Hub URL.
Network Requirements
Device Hub must be accessible from Data Border:
- HTTPS - TLS encryption required
- Authentication - Device Hub should authenticate Data Border requests
- Firewall - Allow inbound from Data Border's IP ranges
Sending Print Jobs
Request Format
curl -X POST https://adb.example.com/api/print/send \
-H "Content-Type: application/json" \
-H "x-seller-access-token: YOUR_SELLER_TOKEN" \
-H "x-amazon-token-secret: YOUR_TOKEN_SECRET" \
-d '{
"shipment_id": "ship_abc123def456",
"printer_type": "label",
"printer_id": "warehouse-1-zebra",
"label_uuids": ["550e8400-e29b-41d4-a716-446655440000"]
}'
Request Fields
| Field | Type | Description |
|---|---|---|
shipment_id | string | Data Border shipment ID from label generation |
printer_type | string | "label" (thermal) or "laser" |
printer_id | string | Target printer identifier in Device Hub |
label_uuids | array | UUIDs of documents to print |
Response
First Print:
{
"success": true,
"data": {
"status": "sent",
"shipment_id": "ship_abc123def456",
"documents_sent": 1,
"print_count": 1,
"is_reprint": false
}
}
Reprint:
{
"success": true,
"data": {
"status": "sent",
"shipment_id": "ship_abc123def456",
"documents_sent": 1,
"print_count": 2,
"is_reprint": true,
"warning": "Reprint detected. First printed: 2024-01-15T10:30:00.000Z"
}
}
Reprint Detection
Data Border tracks how many times each shipment's labels have been printed:
- First print:
print_count: 1,is_reprint: false - Subsequent prints:
print_count: N,is_reprint: true, includes warning
This creates an audit trail for reprints, which can indicate:
- Legitimate reprints (printer jammed, label damaged)
- Potential fraud (duplicate labels)
- Process issues (labels being wasted)
Your WMS can use is_reprint to:
- Show warnings to warehouse staff
- Require supervisor approval for reprints
- Log reprint reasons in your system
Error Handling
Shipment Not Found
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Shipment not found",
"details": "No shipment found with id ship_abc123def456"
}
}
Device Hub Not Configured
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Device Hub not configured for this tenant",
"details": "Contact your administrator to configure the Device Hub host"
}
}
Invalid Label UUIDs
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Invalid label UUIDs",
"details": "The following UUIDs are not part of this shipment: 550e8400-..."
}
}
Device Hub Unreachable
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Device Hub communication failed",
"details": "Connection timeout after 30000ms"
}
}
Printer Types
Label Printers ("label")
Thermal printers like Zebra, DYMO, or Brother:
- Typically 4x6" or 4x8" labels
- ZPL or EPL format
- Direct thermal or thermal transfer
Laser Printers ("laser")
Standard office printers:
- Letter or A4 paper
- PDF format
- For packing slips, invoices, customs forms
Best Practices
Validate UUIDs Before Printing
Store the documents array from label generation and validate before print requests:
// After label generation
const labelResponse = await generateLabel(orderData);
const shipmentId = labelResponse.shipment_id;
const documentUUIDs = labelResponse.documents.map(d => d.uuid);
// Store in your database
await saveShipment({
orderId: orderData.orderId,
shipmentId,
documentUUIDs
});
// Before printing
const shipment = await getShipment(orderId);
const validUUIDs = documentUUIDs.filter(
uuid => shipment.documentUUIDs.includes(uuid)
);
Handle Reprints Appropriately
const printResponse = await sendPrintJob(shipmentId, uuids);
if (printResponse.is_reprint) {
logger.warn({
type: 'print',
shipmentId,
printCount: printResponse.print_count,
firstPrinted: printResponse.warning
}, 'Label reprint detected');
// Optionally require confirmation
if (printResponse.print_count > 2) {
await requireSupervisorApproval(shipmentId);
}
}
Configure Timeouts
The default Device Hub timeout is 30 seconds. For large print jobs or slow networks, consider:
- Printing labels individually rather than in batches
- Implementing retry logic with exponential backoff
- Monitoring Device Hub response times
End-to-End Example
Here's the complete workflow for shipping an Amazon order:
// 1. Generate label with placeholders
const labelResponse = await fetch('/api/label-proxy/forward', {
method: 'POST',
headers: {
'x-seller-access-token': sellerToken,
'x-amazon-token-secret': tokenSecret,
'x-original-url': 'https://api.easypost.com/v2/shipments',
'x-amazon-order-id': amazonOrderId,
'x-unique-shipment-id': `${orderId}-${Date.now()}`
},
body: JSON.stringify({
shipment: {
to_address: {
name: '{{ship_to_name}}',
street1: '{{ship_to_address1}}',
city: '{{ship_to_city}}',
state: '{{ship_to_state}}',
zip: '{{ship_to_zip}}',
country: '{{ship_to_country}}'
},
from_address: warehouseAddress,
parcel: packageDimensions
}
})
});
const { shipment_id, documents } = await labelResponse.json();
// 2. Store shipment info in your WMS
await saveShipment({
orderId,
amazonOrderId,
shipmentId: shipment_id,
trackingNumber: scrubbed_response.tracking_code,
documentUUIDs: documents.map(d => d.uuid)
});
// 3. Print the label
const printResponse = await fetch('/api/print/send', {
method: 'POST',
headers: {
'x-seller-access-token': sellerToken,
'x-amazon-token-secret': tokenSecret
},
body: JSON.stringify({
shipment_id: shipment_id,
printer_type: 'label',
printer_id: workstationPrinter,
label_uuids: documents.map(d => d.uuid)
})
});
// 4. Label prints at workstation
// Your WMS never saw the customer address!
