Developer Docs

Getting Started
  • Quick Start
  • Getting Started
  • Authentication
API Reference
  • Overview
  • Orders
  • Products
  • Inventory
  • Shipments
  • Customers
  • Returns
  • Tracking
Integrations
  • Shopify
  • WooCommerce
  • BigCommerce
  • Custom API
Webhooks
  • Overview
  • Webhook Events
Resources
  • Rate Limits
  • Error Codes
  • API Playground
  • SDK Libraries
  • Changelog
  • API Status
Support
  • Community
  • GitHub
  • Support
HomeDeveloper HubDocsApi ReferenceWebhooks Reference

Webhooks API Reference

Subscribe to real-time events and receive instant notifications when important actions occur in your account.

Overview

Webhooks allow you to receive real-time HTTP notifications when events occur in your 3PL SHIP account. Instead of polling our API, webhooks push data to your application as events happen.

Real-Time Events

Instant notifications as they happen

Secure Delivery

HMAC SHA-256 signature verification

Reliable Retries

Automatic retry with exponential backoff

Create Webhook Subscription

POSThttps://app.3plship.com/api/v1/webhooks

Create a new webhook subscription to receive events at your endpoint.

Request Body
{
  "url": "https://your-domain.com/webhooks/3plship",
  "events": [
    "order.created",
    "order.fulfilled",
    "shipment.tracking_updated",
    "inventory.low_stock"
  ],
  "description": "Production webhook endpoint",
  "active": true
}
Response
{
  "success": true,
  "data": {
    "id": "wh_1234567890",
    "url": "https://your-domain.com/webhooks/3plship",
    "events": [
      "order.created",
      "order.fulfilled",
      "shipment.tracking_updated",
      "inventory.low_stock"
    ],
    "secret": "whsec_K9x7mN2pQ5vR8tY4zB6cD1fH3jL0wE",
    "active": true,
    "created_at": "2025-01-12T10:30:00.000Z"
  },
  "meta": {
    "timestamp": "2025-01-12T10:30:00.000Z",
    "requestId": "req_abc123xyz",
    "version": "v1"
  }
}

Save Your Webhook Secret

The webhook secret is only shown once. Store it securely to verify webhook signatures.

Available Events

Event TypeDescription
order.createdNew order received
order.fulfilledOrder has been fulfilled and shipped
order.shippedOrder shipment created and tracking available
order.deliveredOrder delivered to customer
order.cancelledOrder has been cancelled
shipment.createdShipment label generated
shipment.tracking_updatedTracking status changed
inventory.updatedInventory quantity changed
inventory.low_stockStock level below threshold
return.createdReturn request initiated
return.receivedReturn received at warehouse

Webhook Payload Structure

Example Payload
{
  "id": "evt_1234567890",
  "type": "order.fulfilled",
  "created_at": "2025-01-12T15:30:00.000Z",
  "data": {
    "object": "order",
    "id": "ord_abc123",
    "order_number": "ORD-2025-0001",
    "status": "fulfilled",
    "customer": {
      "email": "customer@example.com",
      "name": "John Doe"
    },
    "shipment": {
      "tracking_number": "1Z999AA10123456784",
      "carrier": "UPS",
      "service": "Ground"
    },
    "fulfilled_at": "2025-01-12T15:30:00.000Z"
  }
}

Verify Webhook Signatures

All webhook requests include an X-Webhook-Signature header containing an HMAC SHA-256 signature. Verify this signature to ensure the request came from 3PL SHIP.

Node.js Example
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(payload).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

// In your webhook handler
app.post('/webhooks/3plship', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = JSON.stringify(req.body);
  
  if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook event
  const event = req.body;
  console.log('Received event:', event.type);
  
  res.status(200).send('OK');
});
Python Example
import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
    """Verify webhook signature using HMAC SHA-256"""
    computed_signature = hmac.new(
        secret.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, computed_signature)

# In your Flask webhook handler
@app.route('/webhooks/3plship', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Webhook-Signature')
    payload = request.get_data(as_text=True)
    
    if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
        return jsonify({'error': 'Invalid signature'}), 401
    
    event = request.json
    print(f"Received event: {event['type']}")
    
    return jsonify({'status': 'ok'}), 200
cURL - Test Webhook Endpoint
curl -X POST https://app.3plship.com/api/v1/webhooks/wh_1234567890/test \
  -H "Authorization: Bearer zl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "order.created"
  }'

Retry Policy

If your endpoint doesn't respond with a 2xx status code, we'll retry the webhook delivery using exponential backoff:

  • Retry 1: After 5 seconds
  • Retry 2: After 1 minute
  • Retry 3: After 10 minutes
  • Retry 4: After 1 hour
  • Retry 5: After 6 hours (final attempt)

After 5 failed attempts, the webhook will be marked as failed and you'll receive an email notification.

Next Steps

Webhooks Guide

Complete setup guide and best practices

Test Webhooks

Send test events to your endpoint