Webhooks Guide
Webhooks push event data to your server the moment something happens — a label is created, a package is delivered, or a tracking status changes. This eliminates the need to poll the tracking endpoint repeatedly.
How it works
sequenceDiagram participant App as Your App participant Envia as Envia API participant Carrier as Carrier Network App->>Envia: Register webhook (Queries API) Envia-->>App: Webhook ID confirmed App->>Envia: Create label (Shipping API) Carrier->>Envia: Status update (picked up) Envia->>App: POST to your webhook URL App-->>Envia: 200 OK
Step 1 — List available webhook types
Before registering, check which event types are available.
curl --request GET \
--url https://queries-test.envia.com/webhook-types \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN"The response returns an array of webhook types, each with an id, name, and description. Use the id value as the type_id when creating a webhook in the next step.
Tip: The tracking status update webhook is the most commonly used type. It replaces the need to poll
POST /ship/generaltrack/.
Step 2 — Register a webhook
Register your HTTPS endpoint for the event type you want to receive.
curl --request POST \
--url https://queries-test.envia.com/webhooks \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"type_id": 3,
"url": "https://your-app.com/webhooks/envia",
"active": 1
}'Response
The response includes a meta field set to "webhook_created" and a data object with the webhook details:
{
"meta": "webhook_created",
"data": {
"id": 4421,
"type": "...",
"url": "https://your-app.com/webhooks/envia",
"active": 1
}
}Save the data.id — you need it to update, deactivate, or test the webhook later.
Step 3 — Handle incoming events
When an event fires, Envia sends an HTTP POST to your registered URL with a JSON payload. The payload includes tracking details such as carrierName, trackingNumber, and status.
Important: The exact payload structure may vary by event type. Use the Test Webhook endpoint (Step 4) to see the real payload format for your webhook type before building your handler.
Receiver implementation
Your endpoint must respond with a 2xx status quickly. Process the payload asynchronously to avoid timeouts.
app.post("/webhooks/envia", (req, res) => {
// Respond immediately
res.status(200).json({ received: true });
// Process asynchronously
const payload = req.body;
console.log("Webhook received:", JSON.stringify(payload));
// Update your database, notify customers, etc.
processWebhookEvent(payload).catch(console.error);
});Step 4 — Test your webhook
Use the Test Webhook endpoint to send a test event to your URL without waiting for a real carrier event.
curl --request POST \
--url https://api-test.envia.com/ship/webhooktest/ \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"tracking_number": "7520610403",
"webhook_url": "https://your-app.com/webhooks/envia"
}'The test endpoint sends a sample payload to the specified webhook_url using the given tracking_number. Check your server logs to confirm the payload arrived.
Managing webhooks
List your webhooks
curl --request GET \
--url https://queries-test.envia.com/webhooks \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN"Update a webhook
curl --request PUT \
--url https://queries-test.envia.com/webhooks/4421 \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN" \
--header "Content-Type: application/json" \
--data '{"url": "https://your-app.com/webhooks/envia-v2", "active": 1}'Deactivate a webhook
Set active to 0 to pause deliveries without deleting the webhook:
curl --request PUT \
--url https://queries-test.envia.com/webhooks/4421 \
--header "Authorization: Bearer $ENVIA_SANDBOX_TOKEN" \
--header "Content-Type: application/json" \
--data '{"active": 0}'Production checklist
Before going live with webhooks, verify:
- Endpoint is publicly reachable via HTTPS
- Responds with
2xxwithin 5 seconds - Processes payloads asynchronously (don't block the response)
- Handles duplicate deliveries with idempotency (use a unique key from the payload to deduplicate)
- Uses separate webhook URLs for sandbox and production
- Tested using the Test Webhook endpoint
- Logs all incoming events for debugging
Troubleshooting
Webhook events are not arriving
- Check that your URL is publicly accessible (not
localhost). - Verify the webhook is
active: 1withGET /webhooks. - Test manually with the Test Webhook endpoint.
- Confirm your firewall/proxy allows POST requests from Envia's servers.
Receiving duplicate events
Implement idempotency by tracking processed events. Use a combination of fields from the payload as a unique key. If you've already processed that combination, skip it.
Webhook endpoint timing out
Return 200 OK immediately and process the payload in a background job or queue. Do not make external API calls before responding.
Related pages:
- Integration Guide — Phase 5 — Webhooks in the integration flow
- Common Queries Endpoints — Webhook management endpoints
- Error Response Formats — How each API returns errors
- Production Readiness Checklist — Go-live checklist
Updated about 24 hours ago
