Webhooks
Webhooks allow your application to receive real-time notifications when events occur in the Flash Americas system. Instead of polling our API for updates, webhooks push event data directly to your application.
Overview
Flash Americas webhooks provide:
- Real-time notifications for shipment events
- Reliable delivery with retry mechanisms
- Secure verification using HMAC signatures
- Event filtering to receive only relevant notifications
- Multiple endpoint support for different event types
Event Types
| Event | Description |
|---|---|
shipment.created | New shipment was created |
shipment.picked_up | Shipment was picked up by carrier |
shipment.in_transit | Shipment is in transit |
shipment.out_for_delivery | Shipment is out for delivery |
shipment.delivered | Shipment was delivered |
shipment.exception | Delivery exception occurred |
shipment.cancelled | Shipment was cancelled |
quote.created | New quote was generated |
quote.expired | Quote has expired |
tracking.updated | Tracking information updated |
Setting Up Webhooks
1. Create Webhook Endpoint
Express.js webhook handlerjavascript
const express = require('express');
const crypto = require('crypto');
const app = express();
// Middleware to capture raw body for signature verification
app.use('/webhooks', express.raw({type: 'application/json'}));
app.post('/webhooks/flash-americas', (req, res) => {
const signature = req.headers['x-flash-americas-signature'];
const payload = req.body;
// Verify webhook signature
if (!verifySignature(payload, signature)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
// Process the webhook event
handleWebhookEvent(event);
res.status(200).send('OK');
});
function verifySignature(payload, signature) {
const secret = process.env.WEBHOOK_SECRET;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === `sha256=${expectedSignature}`;
}
function handleWebhookEvent(event) {
console.log('Received webhook:', event.eventType);
switch (event.eventType) {
case 'shipment.delivered':
notifyCustomer(event.data);
break;
case 'shipment.exception':
handleDeliveryException(event.data);
break;
default:
console.log('Unhandled event type:', event.eventType);
}
}2. Configure Webhook URL
POST /webhookshttp
POST https://api.flashamericas.com/api/v1/webhooks
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonWebhook configurationjson
{
"url": "https://your-app.com/webhooks/flash-americas",
"events": [
"shipment.picked_up",
"shipment.delivered",
"shipment.exception"
],
"secret": "your_webhook_secret_key",
"active": true
}Response
Webhook creation responsejson
{
"success": true,
"data": {
"webhookId": "wh_123456789",
"url": "https://your-app.com/webhooks/flash-americas",
"events": [
"shipment.picked_up",
"shipment.delivered",
"shipment.exception"
],
"secret": "your_webhook_secret_key",
"active": true,
"createdAt": "2025-01-15T10:30:00Z"
}
}Webhook Payload Structure
All webhook payloads follow a consistent structure:
Standard webhook payloadjson
{
"eventId": "evt_550e8400-e29b-41d4-a716-446655440000",
"eventType": "shipment.delivered",
"timestamp": "2025-02-21T16:45:00Z",
"data": {
"shipmentId": "660e8400-e29b-41d4-a716-446655440001",
"trackingNumber": "1234567890",
"status": "DELIVERED",
// Event-specific data
},
"signature": "sha256=abc123..."
}Event Examples
Shipment Delivered
Delivery webhookjson
{
"eventId": "evt_001",
"eventType": "shipment.delivered",
"timestamp": "2025-02-21T16:45:00Z",
"data": {
"shipmentId": "660e8400-e29b-41d4-a716-446655440001",
"trackingNumber": "1234567890",
"status": "DELIVERED",
"deliveredAt": "2025-02-21T16:45:00Z",
"recipient": "J. DOE",
"location": {
"city": "Houston",
"state": "TX",
"country": "US"
},
"signatureUrl": "https://api.flashamericas.com/documents/signature_123.png"
}
}Delivery Exception
Exception webhookjson
{
"eventId": "evt_002",
"eventType": "shipment.exception",
"timestamp": "2025-02-21T15:30:00Z",
"data": {
"shipmentId": "660e8400-e29b-41d4-a716-446655440001",
"trackingNumber": "1234567890",
"status": "EXCEPTION",
"exceptionCode": "001",
"exceptionReason": "RECIPIENT_NOT_AVAILABLE",
"description": "Delivery attempted - no one available",
"location": {
"city": "Houston",
"state": "TX",
"country": "US"
},
"nextAttempt": "2025-02-22T15:00:00Z"
}
}Security
Signature Verification
Always verify webhook signatures to ensure authenticity:
Signature verificationjavascript
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
const expectedHeader = `sha256=${expectedSignature}`;
return crypto.timingSafeEqual(
Buffer.from(signature, 'utf8'),
Buffer.from(expectedHeader, 'utf8')
);
}Best Practices
- Always verify signatures before processing webhook data
- Use HTTPS endpoints for webhook URLs
- Implement idempotency to handle duplicate events
- Return 200 status quickly to acknowledge receipt
- Process asynchronously for long-running operations
Retry Logic
Flash Americas implements automatic retry logic for failed webhook deliveries:
- Initial attempt: Immediate delivery
- Retry 1: After 1 minute
- Retry 2: After 5 minutes
- Retry 3: After 15 minutes
- Retry 4: After 1 hour
- Retry 5: After 6 hours
Webhooks are considered failed if they don't return a 2xx status code.
Managing Webhooks
List Webhooks
GET /webhookshttp
GET https://api.flashamericas.com/api/v1/webhooks
Authorization: Bearer YOUR_API_KEYUpdate Webhook
PUT /webhooks/{id}http
PUT https://api.flashamericas.com/api/v1/webhooks/wh_123456789
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonUpdate webhookjson
{
"url": "https://your-app.com/webhooks/v2/flash-americas",
"events": [
"shipment.picked_up",
"shipment.delivered",
"shipment.exception",
"tracking.updated"
],
"active": true
}Delete Webhook
DELETE /webhooks/{id}http
DELETE https://api.flashamericas.com/api/v1/webhooks/wh_123456789
Authorization: Bearer YOUR_API_KEYTesting Webhooks
Webhook Testing Tool
Use our webhook testing tool to simulate events:
POST /webhooks/testhttp
POST https://api.flashamericas.com/api/v1/webhooks/wh_123456789/test
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonTest webhookjson
{
"eventType": "shipment.delivered",
"data": {
"shipmentId": "test_shipment_123",
"trackingNumber": "TEST123456789",
"status": "DELIVERED"
}
}Local Development
For local development, use tools like ngrok to expose your local server:
Expose local webhook endpointbash
# Install ngrok
npm install -g ngrok
# Expose local port 3000
ngrok http 3000
# Use the generated URL for webhook configuration
# https://abc123.ngrok.io/webhooks/flash-americasError Handling
Handle webhook errors gracefully:
Error handlingjavascript
app.post('/webhooks/flash-americas', async (req, res) => {
try {
const signature = req.headers['x-flash-americas-signature'];
const payload = req.body;
if (!verifySignature(payload, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(payload);
await processWebhookEvent(event);
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook processing error:', error);
// Return 500 to trigger retry
res.status(500).json({
error: 'Internal server error',
eventId: event?.eventId
});
}
});
async function processWebhookEvent(event) {
// Store event for processing
await storeWebhookEvent(event);
// Process in background queue
await addToQueue('webhook-processing', event);
}Next Steps
- Set up tracking to complement webhook notifications
- View integration examples for complete webhook implementations
- Monitor shipments for the full shipping workflow
- Handle rate limiting for high-volume webhook endpoints
