E-commerce Checkout Integration
This guide shows how to integrate Envia into an e-commerce checkout flow — from displaying shipping options to the buyer, to printing a label after payment.
What you'll build
flowchart LR Cart["Cart Page"] --> Checkout["Checkout\n(show rates)"] --> Payment["Payment\nConfirmed"] --> Label["Generate\nLabel"] --> Fulfill["Fulfill\n& Track"] style Checkout fill:#1873dc,color:#fff style Label fill:#059669,color:#fff
Your checkout will:
- Show real-time carrier rates with delivery estimates when the buyer enters their address
- Automatically generate a shipping label after payment
- Send the tracking number to your customer
Architecture overview
Buyer enters address
→ Your frontend calls your backend
→ Your backend calls Envia POST /ship/rate/ (one per carrier)
→ Returns rates + delivery estimates
→ Buyer selects a rate and pays
→ Your backend calls Envia POST /ship/generate/
→ Returns tracking number + label PDF
→ You email the tracking link to the buyer
→ Envia webhook notifies you of delivery status changes
Setup
All code examples below use these base URLs and token. Set ENVIA_ENV=production when you are ready to go live.
// Configuration — defaults to sandbox
const ENVIA_BASE = "https://api-test.envia.com";
const QUERIES_BASE = "https://queries-test.envia.com";
const GEOCODES_BASE = "https://geocodes.envia.com";
// Set ENVIA_TOKEN as an environment variable (see Authentication guide)# Configuration — defaults to sandbox
import os, requests
ENVIA_BASE = "https://api-test.envia.com"
QUERIES_BASE = "https://queries-test.envia.com"
GEOCODES_BASE = "https://geocodes.envia.com"
ENVIA_TOKEN = os.environ["ENVIA_TOKEN"]Step 1 — Validate the address at checkout
When the buyer enters their shipping address, validate it before requesting rates. This prevents failed label purchases later.
curl --request GET \
--url "https://geocodes.envia.com/zipcode/MX/03100" \
--header "Authorization: Bearer $ENVIA_TOKEN"Step 2 — Fetch rates for the checkout page
When the buyer reaches the shipping options step, call the rate endpoint for each carrier you want to offer. The rate endpoint accepts one carrier per request, so call it in parallel for speed.
// Fetch rates from multiple carriers in parallel
async function getShippingRates(origin, destination, packages) {
const carriers = ["dhl", "fedex", "estafeta"];
const ratePromises = carriers.map((carrier) =>
fetch(`${ENVIA_BASE}/ship/rate/`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
origin,
destination,
packages,
shipment: { type: 1, carrier },
}),
}).then((r) => r.json())
);
const results = await Promise.allSettled(ratePromises);
// Flatten and sort by price
return results
.filter((r) => r.status === "fulfilled" && r.value.data?.length)
.flatMap((r) => r.value.data)
.sort((a, b) => parseFloat(a.totalPrice) - parseFloat(b.totalPrice));
}Display rates to the buyer
Show the buyer the available options with price and delivery estimate:
| Carrier | Service | Price | Delivery |
|---|---|---|---|
| DHL | Economy | $185.20 MXN | 3-5 business days |
| FedEx | Standard | $210.00 MXN | 2-3 business days |
| Estafeta | Express | $245.50 MXN | 1-2 business days |
Step 3 — Generate the label after payment
Once the buyer selects a rate and completes payment, create the label using the chosen carrier and service.
// Called after payment confirmation
async function createLabel(origin, destination, packages, carrier, service) {
const response = await fetch(`${ENVIA_BASE}/ship/generate/`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ENVIA_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
origin,
destination,
packages,
shipment: { type: 1, carrier, service },
}),
});
const result = await response.json();
const shipment = result.data[0];
return {
trackingNumber: shipment.trackingNumber,
labelUrl: shipment.label,
trackUrl: shipment.trackUrl,
price: shipment.totalPrice,
};
}Step 4 — Register a webhook for tracking updates
Instead of polling, register a webhook to receive delivery status changes automatically.
curl --request POST \
--url https://queries-test.envia.com/webhooks \
--header "Authorization: Bearer $ENVIA_TOKEN" \
--header "Content-Type: application/json" \
--data '{"type_id": 3, "url": "https://your-store.com/webhooks/envia", "active": 1}'When a status changes, Envia sends a POST to your URL. Use it to update order status and notify the buyer. See the Webhooks Guide for full setup details.
Error handling for checkout
Shipping errors at checkout directly impact conversion. Handle them gracefully:
| Scenario | What to show the buyer | What to do |
|---|---|---|
| No rates returned | "Shipping unavailable for this address" | Validate address first; try different carriers |
| 402 on label creation | "Payment processing error" | Check your Envia account balance |
| 422 on label creation | "Please verify your shipping address" | Re-validate with Geocodes API |
| 5xx errors | "Temporary issue — please try again" | Retry with backoff; see Error Response Formats |
Related pages
- Core Workflow — Full request/response examples for every shipping step
- Integration Guide — End-to-end integration walkthrough
- Webhooks Guide — Set up real-time tracking notifications
- Production Readiness Checklist — Go-live checklist
Updated about 12 hours ago
