Shipsidekick LogoShipsidekick Docs
Guides

Webhooks Guide

Learn how to set up and use webhooks to receive real-time notifications from Shipsidekick

Webhooks Guide

Shipsidekick uses webhooks to notify your applications when events happen in your account. Webhooks are particularly useful for tracking shipments, monitoring order updates, and handling billing adjustments.

Understanding Webhooks

Webhooks are HTTP callbacks (or push notifications) that keep your applications up-to-date on the status of Shipsidekick objects in real-time.

  • Eliminate polling: Webhooks eliminate the need to continuously poll our API for updates
  • Real-time updates: When triggered, each webhook sends an Event via HTTP POST request to your configured webhook URL
  • Reliable delivery: A successful 2XX response is expected from each webhook; in the event of a failure, Shipsidekick retries the webhook
  • Multiple formats: Support for both Shipsidekick native format and EasyPost-compatible format

Prerequisites

  • An active Shipsidekick account
  • A publicly accessible HTTPS endpoint to receive webhooks
  • Application readiness to handle and process webhook events
  • Use HMAC validation or basic authentication with HTTPS to secure the webhook endpoint

Webhook Authentication

Securing webhook endpoints is crucial to ensure data integrity and authenticity. Shipsidekick supports two primary methods for securing webhooks:

HMAC validation ensures webhook data is untampered during transmission. When creating a webhook endpoint, include a secret value. Shipsidekick generates an HMAC-SHA256 signature using this secret and sends it via the X-SSK-Signature header in each event.

To validate the webhook:

  1. Extract the signature from the X-SSK-Signature header
  2. Generate your own HMAC-SHA256 signature using your secret and the raw request body
  3. Compare the signatures using a constant-time comparison function
  4. If they match, the webhook is valid; otherwise, reject the event
const crypto = require("crypto");
 
function validateWebhook(payload, signature, secret) {
  const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
 
  return crypto.timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expectedSignature, "hex"));
}

Basic Authentication

Basic authentication requires embedding a username and password in the webhook URL:

https://username:password@your-domain.com/webhook-endpoint

Shipsidekick will include an Authorization header with the credentials. Validate these credentials against your stored values before processing the webhook.

Event Types and Headers

Shipsidekick adds an X-SSK-Webhook-Event-Type header to all webhook requests, allowing you to quickly identify the event type without parsing the entire payload.

Common event types include:

  • tracker.created - A new tracking number has been added
  • tracker.updated - Tracking status has changed
  • shipment.invoice.created - A billing adjustment has been created
  • order.updated - Order status has changed

Response Requirements

Response Time

Webhooks require a response within 10 seconds. If no response is received, Shipsidekick will automatically retry the webhook.

Recommendation: Process the event in a background worker and immediately return a 2XX status code to avoid duplicate notifications.

Expected Status Codes

  • Return any 2XX status code to indicate successful receipt
  • 200 OK or 202 Accepted are preferred
  • Any non-2XX response will trigger a retry

Retry Logic

Shipsidekick will retry failed webhook deliveries with exponential backoff:

  • Maximum retries: 6 attempts
  • Timeout: 10 seconds per attempt
  • Backoff: Increasing delay between retries

Webhook Event Structure

All webhook events follow this structure:

{
  "description": "event.type",
  "mode": "production",
  "previous_attributes": {},
  "pending_urls": ["https://your-endpoint.com/webhook"],
  "completed_urls": [],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "id": "evt_abc123",
  "object": "Event",
  "result": {
    // Event-specific object data
  }
}

Event Properties

  • description: The event type that triggered this webhook
  • mode: Either "production" or "test"
  • previous_attributes: Object containing the previous values of any changed fields
  • pending_urls: URLs that haven't received the webhook yet
  • completed_urls: URLs that have successfully received the webhook
  • result: The object that triggered the event (e.g., Tracker, Order, etc.)

Security Best Practices

HTTPS Required

All webhook endpoints must use HTTPS with valid TLS certificates from trusted certificate authorities.

Validate Signatures

Always validate webhook signatures using HMAC verification to ensure data integrity.

Sensitive Data

Webhook payloads may contain sensitive information. Ensure your endpoint:

  • Uses HTTPS encryption
  • Validates the signature before processing
  • Logs webhook data securely
  • Follows your organization's data protection policies

Testing Webhooks

Test Environment

Webhooks in the test environment behave identically to production webhooks, making it easy to develop and test your integration.

Local Development

For local testing, you can use tools like:

Example Test Endpoint

const express = require("express");
const app = express();
 
app.use(express.raw({ type: "application/json" }));
 
app.post("/webhook", (req, res) => {
  const signature = req.headers["x-ssk-signature"];
  const eventType = req.headers["x-ssk-webhook-event-type"];
 
  if (!validateWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send("Invalid signature");
  }
 
  const event = JSON.parse(req.body);
  console.log(`Received ${eventType} event:`, event);
 
  // Process the event asynchronously
  processWebhookEvent(event);
 
  res.status(200).send("OK");
});

Common Event Examples

Tracker Updated Event

{
  "description": "tracker.updated",
  "mode": "production",
  "previous_attributes": {
    "status": "in_transit"
  },
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "id": "evt_abc123",
  "object": "Event",
  "result": {
    "id": "trk_def456",
    "object": "Tracker",
    "tracking_code": "1Z999AA1234567890",
    "status": "delivered",
    "carrier": "UPS",
    "tracking_details": [
      {
        "status": "delivered",
        "description": "Package delivered",
        "datetime": "2024-01-15T10:25:00Z"
      }
    ]
  }
}

Troubleshooting

Common Issues

Webhook not received:

  • Verify your endpoint is publicly accessible via HTTPS
  • Check that your endpoint returns a 2XX status code within 10 seconds
  • Ensure your firewall allows incoming connections

Signature validation failing:

  • Verify you're using the correct secret
  • Ensure you're using the raw request body (not parsed JSON)
  • Use HMAC-SHA256 for signature generation

Duplicate events:

  • Webhooks may be retried if your endpoint doesn't respond quickly enough
  • Implement idempotency by tracking processed event IDs
  • Return a 2XX status code immediately, then process asynchronously

FAQs

Q: How many webhook endpoints can I configure?
A: You can configure up to 30 webhook endpoints per organization.

Q: What happens if my endpoint is down?
A: Shipsidekick will retry the webhook up to 6 times with exponential backoff.

Q: Can I receive webhooks for events I didn't create?
A: Yes, if you have appropriate permissions for the organization, you'll receive webhooks for all relevant events.

Q: How long are webhook events stored?
A: Webhook events are stored for 30 days and can be retrieved via the API if needed.

Next Steps