Shipping Webhooks

Receive real-time shipping event notifications via webhooks.

Overview

Webhooks allow your application to receive real-time notifications when shipping events occur. Register a webhook endpoint in your Developer Dashboard, and Peeap will send signed POST requests to your URL whenever the subscribed events happen.

Webhook Management: Register and manage webhook endpoints via the Developer Dashboard at https://my.peeap.com/merchant/developer or programmatically via POST /v1/webhooks.

Shipping Events

shipping.delivery.created

Triggered when a new delivery job is created. This event contains the delivery details, including the job number, addresses, and handoff codes.

json
{
  "event": "shipping.delivery.created",
  "livemode": true,
  "created": 1721640000,
  "data": {
    "object": {
      "job_number": "SHP-A1B2C3D4-X5Y6",
      "transaction_id": "txn_abc123",
      "order_number": "MKT-ABC123",
      "store_name": "Tech Store",
      "delivery_address": "456 Main Rd, Bo",
      "delivery_city": "Bo",
      "pickup_code": "4821",
      "delivery_code": "7395",
      "shipping_fee": 25.00,
      "status": "assigned"
    }
  }
}

shipping.status.updated

Triggered whenever a delivery's status changes. This includes driver assignment, pickup, transit updates, delivery completion, and cancellations.

json
{
  "event": "shipping.status.updated",
  "livemode": true,
  "created": 1721643600,
  "data": {
    "object": {
      "transaction_id": "txn_abc123",
      "job_number": "SHP-A1B2C3D4-X5Y6",
      "status": "in_transit",
      "order_status": "shipped",
      "pickup_verified": true,
      "delivery_verified": false,
      "order_number": "MKT-ABC123"
    }
  }
}

Signature Verification

Every webhook request includes a signature header that you must verify to ensure the request genuinely came from Peeap. The signature is an HMAC-SHA256 hash of the raw request body, computed using your webhook signing secret.

Headers

HeaderDescription
X-Peeap-SignatureHMAC-SHA256 signature of the request body
X-Peeap-EventThe event type (e.g. shipping.status.updated)

Verification Example (Node.js)

javascript
class="code-keyword">const crypto = class="code-function">require(class="code-keyword">class="code-string">'crypto');

class="code-keyword">function class="code-function">verifyWebhookSignature(body, signature, secret) {
  class="code-keyword">const expected = crypto
    .class="code-function">createHmac(class="code-keyword">class="code-string">'sha256', secret)
    .class="code-function">update(JSON.class="code-function">stringify(body))
    .class="code-function">digest(class="code-keyword">class="code-string">'hex');
  class="code-keyword">return crypto.class="code-function">timingSafeEqual(
    Buffer.class="code-keyword">from(expected),
    Buffer.class="code-keyword">from(signature)
  );
}

class="code-keyword">class=class="code-keyword">class="code-string">"code-comment">// Express.js middleware example
app.class="code-function">post(class="code-keyword">class="code-string">'/webhooks/peeap', (req, res) => {
  class="code-keyword">const signature = req.headers[class="code-keyword">class="code-string">'x-peeap-signature'];
  class="code-keyword">const event = req.headers[class="code-keyword">class="code-string">'x-peeap-event'];

  class="code-keyword">if (!class="code-function">verifyWebhookSignature(req.body, signature, process.env.PEEAP_WEBHOOK_SECRET)) {
    class="code-keyword">return res.class="code-function">status(401).class="code-function">json({ error: class="code-keyword">class="code-string">'Invalid signature' });
  }

  class="code-function">switch(event) {
    case class="code-keyword">class="code-string">'shipping.delivery.created':
      console.class="code-function">log(class="code-keyword">class="code-string">'New delivery:', req.body.data.object.job_number);
      break;
    case class="code-keyword">class="code-string">'shipping.status.updated':
      console.class="code-function">log(class="code-keyword">class="code-string">'Status update:', req.body.data.object.status);
      break;
  }

  res.class="code-function">status(200).class="code-function">json({ received: class="code-keyword">true });
});

Best Practices

  • Always verify signatures — Use the signing secret shown once when creating the webhook to verify every request.
  • Respond quickly — Your endpoint should respond with a 200 status within 10 seconds. Heavy processing should be queued.
  • Expect retries — If your endpoint returns a non-200 status, Peeap will retry up to 3 times with exponential backoff.
  • Use idempotent processing — The same event may be delivered more than once. Use the job number and status to detect duplicates.
  • Monitor deliveries — Use the Developer Dashboard to view delivery logs and redeliver failed events after fixing your endpoint.