Pickup & Manifest Workflow
TL;DR — High-volume pickup with manifests:
- Create labels →
POST /ship/generate/for each shipment (Shipping)- Create manifest →
POST /ship/manifestto consolidate all labels (Shipping)- Schedule pickup →
POST /ship/pickup/with tracking numbers (Shipping)- Track all →
POST /ship/generaltrack/(Shipping)
flowchart LR L["Create Labels\n(batch)"] --> M["Create\nManifest"] --> P["Schedule\nPickup"] --> T["Track All"] style L fill:#1873dc,color:#fff style M fill:#d97706,color:#fff style P fill:#059669,color:#fff
Meet Ana
Ana manages warehouse operations for MegaStore, a large e-commerce retailer in Mexico City. Every day, her warehouse processes 50-100 orders that need to be shipped to customers across Mexico. Instead of making individual trips to carrier branches or scheduling multiple pickups, Ana needs an efficient system to create labels, organize packages, and have carriers collect them all at once. She uses manifests to consolidate shipments and streamline her daily operations.
Why Use Manifests?
For high-volume shippers like Ana, manifests provide several key benefits:
| Benefit | Description |
|---|---|
| Organization | Consolidate all daily shipments into one document |
| Efficiency | Schedule one pickup instead of multiple trips |
| Proof of Shipment | Official document showing all packages handed to carrier |
| Warehouse Management | Easy reference for warehouse staff preparing packages |
| Claims Support | Documentation for insurance or lost package claims |
The Journey
Ana's daily workflow for high-volume shipping:
Step-by-Step Workflow
Step 1: Create Multiple Labels
What Ana needs to do: Throughout the day, Ana's system creates shipping labels for each order. By end of day, she has 50+ labels ready. Each label has a tracking number that she'll need for the manifest.
API Call: Create Shipping Label from the Shipping API
Ana's system creates labels programmatically. Here's an example of creating one label (her system repeats this for each order):
# Example: Creating a label for one order
curl --request POST \
--url "https://api-test.envia.com/ship/generate/" \
--header "Authorization: Bearer $ENVIA_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"origin": {
"name": "Ana Garcia",
"company": "MegaStore Warehouse",
"phone": "+52 5551112233",
"email": "[email protected]",
"street": "Av. Industrial 500",
"city": "Ciudad de Mexico",
"state": "CX",
"country": "MX",
"postalCode": "07800"
},
"destination": {
"name": "Customer Name",
"phone": "+52 8181234567",
"street": "Customer Street",
"city": "Monterrey",
"state": "NL",
"country": "MX",
"postalCode": "64060"
},
"packages": [
{
"type": "box",
"content": "Products",
"amount": 1,
"declaredValue": 500,
"weight": 1.2,
"weightUnit": "KG",
"lengthUnit": "CM",
"dimensions": {
"length": 30,
"width": 25,
"height": 15
}
}
],
"shipment": {
"type": 1,
"carrier": "estafeta",
"service": "estafeta_terrestre"
}
}'// Ana's system creates labels in a loop for each order
async function createLabelsForOrders(orders) {
const trackingNumbers = [];
for (const order of orders) {
const response = await fetch("https://api-test.envia.com/ship/generate/", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
origin: {
name: "Ana Garcia",
company: "MegaStore Warehouse",
phone: "+52 5551112233",
email: "[email protected]",
street: "Av. Industrial 500",
city: "Ciudad de Mexico",
state: "CX",
country: "MX",
postalCode: "07800",
},
destination: order.destination,
packages: order.packages,
shipment: {
type: 1,
carrier: "estafeta",
service: "estafeta_terrestre",
},
}),
});
const label = await response.json();
trackingNumbers.push(label.trackingNumber);
}
return trackingNumbers; // All tracking numbers for the manifest
}
// At end of day, Ana has all tracking numbers
const allTrackingNumbers = await createLabelsForOrders(dailyOrders);
console.log("Total labels created:", allTrackingNumbers.length);import requests
import os
import json
# Ana's system creates labels in a loop for each order
def create_labels_for_orders(orders):
tracking_numbers = []
for order in orders:
response = requests.post(
"https://api-test.envia.com/ship/generate/",
headers={
"Authorization": f"Bearer {os.getenv('ENVIA_TOKEN')}",
"Content-Type": "application/json"
},
json={
"origin": {
"name": "Ana Garcia",
"company": "MegaStore Warehouse",
"phone": "+52 5551112233",
"email": "[email protected]",
"street": "Av. Industrial 500",
"city": "Ciudad de Mexico",
"state": "CX",
"country": "MX",
"postalCode": "07800"
},
"destination": order["destination"],
"packages": order["packages"],
"shipment": {
"type": 1,
"carrier": "estafeta",
"service": "estafeta_terrestre"
}
}
)
label = response.json()
tracking_numbers.append(label["trackingNumber"])
return tracking_numbers # All tracking numbers for the manifest
# At end of day, Ana has all tracking numbers
all_tracking_numbers = create_labels_for_orders(daily_orders)
print(f"Total labels created: {len(all_tracking_numbers)}")Response example
{
"meta": "generate",
"data": [
{
"carrier": "estafeta",
"service": "estafeta_terrestre",
"shipmentId": 987654,
"trackingNumber": "EST123456789",
"trackUrl": "https://tracking.envia.com/EST123456789",
"label": "https://files.envia.com/labels/EST123456789.pdf",
"totalPrice": 125.5,
"currency": "MXN"
}
]
}Ana's efficiency tip: Ana's system collects all tracking numbers throughout the day. By end of day, she has a complete list ready to create the manifest.
Step 2: Create Manifest
What Ana needs to do: At the end of the day, Ana consolidates all 50+ shipments into one manifest. This creates a single document listing all packages that will be picked up together.
API Call: Create Manifest from the Shipping API
# Ana creates manifest with all tracking numbers from the day
curl --request POST \
--url "https://api-test.envia.com/ship/manifest" \
--header "Authorization: Bearer $ENVIA_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"trackingNumbers": [
"EST123456789",
"EST123456790",
"EST123456791",
"EST123456792",
"EST123456793"
# ... (50+ tracking numbers)
]
}'// At end of day, Ana creates manifest with all tracking numbers
async function createDailyManifest(trackingNumbers) {
const response = await fetch("https://api-test.envia.com/ship/manifest", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
trackingNumbers: trackingNumbers, // Array of 50+ tracking numbers
}),
});
const manifest = await response.json();
console.log("Manifest ID:", manifest.manifestId);
console.log("Manifest URL:", manifest.manifestUrl);
console.log("Total packages:", trackingNumbers.length);
return manifest;
}
// Ana creates the manifest
const dailyManifest = await createDailyManifest(allTrackingNumbers);
// Manifest document is ready to print for warehouse and carrierimport requests
import os
import json
# At end of day, Ana creates manifest with all tracking numbers
def create_daily_manifest(tracking_numbers):
response = requests.post(
"https://api-test.envia.com/ship/manifest",
headers={
"Authorization": f"Bearer {os.getenv('ENVIA_TOKEN')}",
"Content-Type": "application/json"
},
json={
"trackingNumbers": tracking_numbers # List of 50+ tracking numbers
}
)
manifest = response.json()
print(f"Manifest ID: {manifest['manifestId']}")
print(f"Manifest URL: {manifest['manifestUrl']}")
print(f"Total packages: {len(tracking_numbers)}")
return manifest
# Ana creates the manifest
daily_manifest = create_daily_manifest(all_tracking_numbers)
# Manifest document is ready to print for warehouse and carrierResponse example
{
"meta": "manifest",
"data": {
"manifestId": "MAN-2025-001",
"manifestUrl": "https://files.envia.com/manifests/MAN-2025-001.pdf",
"totalPackages": 50,
"carrier": "estafeta"
}
}Ana's workflow: The manifest document lists all packages with their tracking numbers. Ana prints this manifest and uses it to:
- Organize packages in the warehouse
- Verify all packages are ready for pickup
- Provide proof of shipment to the carrier
- Keep records for claims or audits
Step 3: Schedule Daily Pickup
What Ana needs to do: Ana schedules one pickup for all packages. She includes all tracking numbers in the pickup request, and the carrier will collect everything during the scheduled time window.
Pickup Rules: Pickup requirements vary by carrier. Ana should verify cutoff times, available business days, and minimum package counts with each carrier before scheduling. Use the Queries API to check carrier-specific pickup options.
API Call: Schedule Pickup from the Shipping API
Example body vs API reference: The request body below uses a simplified flat structure. The canonical API schema uses
originandshipment.pickupas nested objects. Always verify the exact request shape in the Schedule Pickup reference before integrating.
curl --request POST \
--url "https://api-test.envia.com/ship/pickup/" \
--header "Authorization: Bearer $ENVIA_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"carrier": "estafeta",
"pickupAddress": {
"name": "Ana Garcia",
"company": "MegaStore Warehouse",
"phone": "+52 5551112233",
"email": "[email protected]",
"street": "Av. Industrial 500",
"city": "Ciudad de Mexico",
"state": "CX",
"country": "MX",
"postalCode": "07800"
},
"pickupDate": "2025-01-27",
"pickupTimeStart": "16:00",
"pickupTimeEnd": "18:00",
"trackingNumbers": [
"EST123456789",
"EST123456790",
"EST123456791"
# ... (all 50+ tracking numbers)
]
}'// Ana schedules one pickup for all packages
async function scheduleDailyPickup(trackingNumbers) {
const response = await fetch("https://api-test.envia.com/ship/pickup/", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
carrier: "estafeta",
pickupAddress: {
name: "Ana Garcia",
company: "MegaStore Warehouse",
phone: "+52 5551112233",
email: "[email protected]",
street: "Av. Industrial 500",
city: "Ciudad de Mexico",
state: "CX",
country: "MX",
postalCode: "07800",
},
pickupDate: "2025-01-27",
pickupTimeStart: "16:00",
pickupTimeEnd: "18:00",
trackingNumbers: trackingNumbers, // All 50+ tracking numbers
}),
});
const pickup = await response.json();
console.log("Pickup scheduled:", pickup);
console.log("Expected pickup time:", pickup.pickupWindow);
return pickup;
}
// Ana schedules the pickup
const pickupConfirmation = await scheduleDailyPickup(allTrackingNumbers);import requests
import os
import json
# Ana schedules one pickup for all packages
def schedule_daily_pickup(tracking_numbers):
response = requests.post(
"https://api-test.envia.com/ship/pickup/",
headers={
"Authorization": f"Bearer {os.getenv('ENVIA_TOKEN')}",
"Content-Type": "application/json"
},
json={
"carrier": "estafeta",
"pickupAddress": {
"name": "Ana Garcia",
"company": "MegaStore Warehouse",
"phone": "+52 5551112233",
"email": "[email protected]",
"street": "Av. Industrial 500",
"city": "Ciudad de Mexico",
"state": "CX",
"country": "MX",
"postalCode": "07800"
},
"pickupDate": "2025-01-27",
"pickupTimeStart": "16:00",
"pickupTimeEnd": "18:00",
"trackingNumbers": tracking_numbers # All 50+ tracking numbers
}
)
pickup = response.json()
print("Pickup scheduled:", pickup)
print("Expected pickup time:", pickup.get("pickupWindow"))
return pickup
# Ana schedules the pickup
pickup_confirmation = schedule_daily_pickup(all_tracking_numbers)Response example
{
"meta": "pickup",
"data": {
"carrier": "estafeta",
"confirmation": "PKP-2025-001",
"status": "scheduled",
"date": "2025-01-27",
"timeFrom": 16,
"timeTo": 18
}
}Ana's efficiency: Instead of making 50+ individual trips to carrier branches or scheduling multiple pickups, Ana schedules one daily pickup. The carrier arrives during the time window, collects all packages using the manifest, and Ana's warehouse operations run smoothly.
Step 4: Track All Shipments
What Ana needs to do: Ana wants to monitor all shipments and provide updates to customers. She can track multiple shipments in batches.
API Call: Track Shipments from the Shipping API
# Ana tracks shipments (POST with JSON body; batch if needed per API limits)
curl --request POST \
--url "https://api-test.envia.com/ship/generaltrack/" \
--header "Authorization: Bearer $ENVIA_TOKEN" \
--header "Content-Type: application/json" \
--data '{"trackingNumbers": ["7520610403", "7520610404", "7520610405"]}'// Ana tracks shipments in batches (POST with JSON body)
async function trackShipmentsBatch(trackingNumbers) {
const batchSize = 50;
const batches = [];
for (let i = 0; i < trackingNumbers.length; i += batchSize) {
batches.push(trackingNumbers.slice(i, i + batchSize));
}
const allStatuses = [];
for (const batch of batches) {
const response = await fetch(
"https://api-test.envia.com/ship/generaltrack/",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ trackingNumbers: batch }),
}
);
const result = await response.json();
if (result.data) allStatuses.push(...result.data);
}
return allStatuses;
}
// Ana tracks all shipments
const allStatuses = await trackShipmentsBatch(allTrackingNumbers);
console.log(`Tracking ${allStatuses.length} shipments`);import requests
import os
# Ana tracks shipments in batches (POST with JSON body)
def track_shipments_batch(tracking_numbers):
batch_size = 50
batches = [
tracking_numbers[i:i + batch_size]
for i in range(0, len(tracking_numbers), batch_size)
]
all_statuses = []
for batch in batches:
response = requests.post(
"https://api-test.envia.com/ship/generaltrack/",
headers={
"Authorization": f"Bearer {os.getenv('ENVIA_TOKEN')}",
"Content-Type": "application/json",
},
json={"trackingNumbers": batch},
)
data = response.json()
if data.get("data"):
all_statuses.extend(data["data"])
return all_statuses
# Ana tracks all shipments
all_statuses = track_shipments_batch(all_tracking_numbers)
print(f"Tracking {len(all_statuses)} shipments")Response example
{
"meta": "track",
"data": [
{
"trackingNumber": "EST123456789",
"status": "In transit",
"carrier": "estafeta",
"events": [
{
"timestamp": "2025-01-27T16:30:00Z",
"location": "Ciudad de Mexico, MX",
"description": "Shipment picked up"
}
]
}
]
}Comparison: Individual vs Manifest Workflow
Ana's workflow comparison:
| Aspect | Individual Pickups | Manifest Workflow |
|---|---|---|
| Number of Pickups | 50+ separate pickups | 1 daily pickup |
| Time Spent | Hours coordinating multiple pickups | Minutes scheduling one pickup |
| Organization | Packages scattered, hard to track | All packages in one manifest |
| Documentation | Individual receipts for each | One manifest document |
| Efficiency | Low - multiple trips/coordination | High - streamlined process |
| Scalability | Doesn't scale well | Scales easily with volume |
What Ana Learned
Through managing high-volume shipping, Ana discovered:
- Manifests are essential - They organize large volumes of shipments into manageable documents
- Batch operations save time - Creating labels programmatically and consolidating into manifests is much more efficient
- Single daily pickup is optimal - One scheduled pickup for all packages streamlines warehouse operations
- Documentation matters - Manifests serve as proof of shipment and help with claims
- The workflow scales - As order volume grows, the manifest workflow continues to work efficiently
Ana's warehouse now processes 100+ orders daily with the same streamlined workflow. Her team is organized, carriers collect packages efficiently, and customers receive their orders on time!
What to read next
- Multi-box orders? – See Shipping Multiple Packages for handling orders with multiple boxes.
- Set up notifications – The Webhooks Guide covers real-time tracking updates for your warehouse dashboard.
- 3PL scenario – The Warehouse & 3PL Automation use case shows how to scale this workflow.
- Going live? – Use the Production Readiness Checklist before switching to production.
Related references
Updated 4 months ago
