Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.waysdrop.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks

Waysdrop sends webhooks for key order and delivery lifecycle events. Webhooks are delivered asynchronously and retried on failure.

Delivery & signature

Webhook payloads are POSTed to the webhook URL configured for the API key.

Environments

Webhooks are scoped to the environment of the API key:
  • Live: https://api.waysdrop.com
  • Staging: https://staging-api.waysdrop.com
Configure your webhook URL in the matching dashboard:

Payload

{
    "event": "delivery.in.transit",
    "data": {}
}

Headers

  • Content-Type: application/json
  • User-Agent: Waysdrop-Webhook/1.0
  • X-Webhook-Log-Id: <logId>
  • x-waysdrop-signature: <hex signature>
Idempotency Use X-Webhook-Log-Id as an idempotency key. The same event may be retried and delivered more than once; you should safely ignore duplicates by storing processed log IDs.

Signature

x-waysdrop-signature is computed as:
  • Algorithm: sha256
  • Secret: your API key value (the same string you send in api-key)
  • Input: JSON.stringify({ event, data })
Verification example (Node.js)
import crypto from "crypto";

export function verifyWaysdropSignature({ apiKey, body, signature }) {
    const computed = crypto
        .createHmac("sha256", apiKey)
        .update(body)
        .digest("hex");
    return crypto.timingSafeEqual(
        Buffer.from(computed),
        Buffer.from(signature),
    );
}

Your webhook response

Waysdrop treats any successful 2xx response as “delivered”. Your endpoint should respond quickly (Waysdrop times out at 5 seconds). Recommended response
{
    "received": true
}
Waysdrop stores your response body in the webhook log for debugging (if any).

Retries and delivery guarantees

Webhooks are delivered asynchronously and retried until one of these happens:
  • delivered successfully
  • exhausted retry attempts (max: 10)
Retry conditions
  • Retries on network errors/timeouts.
  • Retries on 408 and 429.
  • Retries on all 5xx.
  • Does not retry for other 4xx responses.
Backoff
  • nextRetryAt uses exponential backoff: 2^attempts seconds.
  • A repeat job runs roughly every 60 seconds and attempts retries once nextRetryAt is due.

Webhook events

All timestamps are serialized as ISO strings.

p2p.delivery.created

{
    "event": "p2p.delivery.created",
    "data": {
        "status": "string",
        "trackingId": "string",
        "deliveryId": "uuid",
        "p2pDeliveryId": "uuid",
        "userId": "uuid",
        "profileId": "uuid",
        "totalWeight": "number",
        "totalValue": "number",
        "costs": {
            "total": "number",
            "weight": "number",
            "urgency": "number",
            "fleet": "number",
            "insurance": "number",
            "base": "number"
        },
        "paymentMethodType": "string",
        "courierSelection": "string",
        "urgencyType": "string",
        "origin": {},
        "destination": {},
        "createdAt": "2026-01-24T12:34:56.789Z"
    }
}

p2p.delivery.cancelled

{
    "event": "p2p.delivery.cancelled",
    "data": {
        "trackingId": "string",
        "deliveryId": "uuid",
        "p2pDeliveryId": "uuid",
        "status": "CANCELLED",
        "canceledAt": "2026-01-24T12:34:56.789Z",
        "refundAmount": "number | null"
    }
}

delivery.request.accepted

{
    "event": "delivery.request.accepted",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "ACCEPTED",
        "routeType": "string",
        "courierProfileId": "uuid",
        "origin": {},
        "destination": {},
        "storeProfileId": "uuid",
        "storeLocation": {},
        "orderId": "uuid",
        "p2pDeliveryId": "uuid"
    }
}

delivery.request.declined

{
    "event": "delivery.request.declined",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "DECLINED",
        "routeType": "string",
        "courierProfileId": "uuid",
        "courierUserId": "uuid",
        "origin": {},
        "destination": {},
        "storeProfileId": "uuid",
        "storeLocation": {},
        "orderId": "uuid",
        "orderNumber": "string",
        "p2pDeliveryId": "uuid",
        "refundExpected": {
            "amount": "number",
            "currency": "string"
        }
    }
}

delivery.awaiting.collection

{
    "event": "delivery.awaiting.collection",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "AWAITING_COLLECTION",
        "routeType": "string",
        "courierProfileId": "uuid",
        "origin": {},
        "destination": {},
        "proofCode": "string | null",
        "orderId": "uuid",
        "storeProfileId": "uuid",
        "p2pDeliveryId": "uuid",
        "profileId": "uuid",
        "updatedAt": "2026-01-24T12:34:56.789Z"
    }
}

delivery.collected

{
    "event": "delivery.collected",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "ORDER_COLLECTED | PACKAGE_COLLECTED",
        "routeType": "string",
        "collectedAt": "2026-01-24T12:34:56.789Z",
        "courierProfileId": "uuid",
        "courierUserId": "uuid",
        "origin": {},
        "destination": {},
        "deliveryCode": "string | null",
        "orderId": "uuid",
        "storeProfileId": "uuid",
        "p2pDeliveryId": "uuid"
    }
}

delivery.in.transit

{
    "event": "delivery.in.transit",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "IN_TRANSIT",
        "routeType": "string",
        "origin": {},
        "destination": {},
        "inTransitAt": "2026-01-24T12:34:56.789Z"
    }
}

delivery.delivered

{
    "event": "delivery.delivered",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "DELIVERED",
        "routeType": "string",
        "deliveredAt": "2026-01-24T12:34:56.789Z",
        "courierProfileId": "uuid",
        "courierUserId": "uuid",
        "origin": {},
        "destination": {},
        "orderId": "uuid",
        "storeProfileId": "uuid",
        "p2pDeliveryId": "uuid"
    }
}

delivery.reassignment.created

Emitted when a courier-to-system reassignment is created for one or more deliveries (grouped by apiKeyId).
{
    "event": "delivery.reassignment.created",
    "data": {
        "reassignmentId": "uuid",
        "type": "string",
        "status": "string",
        "fromCourierId": "uuid",
        "handoverLocation": {},
        "deliveryIds": ["uuid"],
        "trackingIds": ["string"],
        "createdAt": "2026-01-24T12:34:56.789Z"
    }
}

delivery.reassignment.requested

Emitted when the system creates a reassignment request response for a candidate courier (grouped by apiKeyId).
{
    "event": "delivery.reassignment.requested",
    "data": {
        "reassignmentId": "uuid",
        "status": "string",
        "type": "string",
        "courierProfileId": "uuid",
        "handoverLocation": {},
        "dominantFleetTypeId": "uuid",
        "deliveryIds": ["uuid"],
        "trackingIds": ["string"],
        "requestedAt": "2026-01-24T12:34:56.789Z"
    }
}

delivery.reassignment.collected

Emitted after reassignment handover proof is validated (grouped by apiKeyId).
{
    "event": "delivery.reassignment.collected",
    "data": {
        "reassignmentId": "uuid",
        "type": "string",
        "status": "string",
        "handoverAt": "2026-01-24T12:34:56.789Z",
        "handoverLocation": {},
        "proofImage": "string | null",
        "fromCourierId": "uuid | null",
        "toCourierId": "uuid | null",
        "deliveries": [
            {
                "deliveryId": "uuid",
                "trackingId": "string",
                "type": "ORDER | P2P",
                "status": "string",
                "routeType": "string",
                "origin": {},
                "destination": {}
            }
        ]
    }
}

delivery.reassignment.direct_assigned

Emitted when an employer directly reassigns deliveries to an employee (no request/proof flow).
{
    "event": "delivery.reassignment.direct_assigned",
    "data": {
        "deliveryId": "uuid",
        "trackingId": "string",
        "type": "ORDER | P2P",
        "status": "string",
        "routeType": "string",
        "reassignmentType": "string",
        "fromCourierId": "uuid",
        "toCourierId": "uuid",
        "assignedAt": "2026-01-24T12:34:56.789Z"
    }
}

order.requested

Emitted when a store receives a new order request.
{
    "event": "order.requested",
    "data": {
        "order": {},
        "storeProfileId": "uuid",
        "storeUserId": "uuid"
    }
}

order.created

{
    "event": "order.created",
    "data": {
        "orderId": "uuid",
        "orderNumber": "string",
        "deliveryId": "uuid",
        "trackingId": "string",
        "userId": "uuid",
        "profileId": "uuid",
        "amount": "number",
        "source": "string",
        "status": "AWAITING_CONFIRMATION"
    }
}

order.confirmed

{
    "event": "order.confirmed",
    "data": {
        "orderId": "uuid",
        "orderNumber": "string",
        "deliveryId": "uuid",
        "trackingId": "string | null",
        "storeProfileId": "uuid",
        "storeUserId": "uuid",
        "storeLocation": {},
        "status": "CONFIRMED",
        "confirmedAt": "2026-01-24T12:34:56.789Z"
    }
}

order.declined

{
    "event": "order.declined",
    "data": {
        "orderId": "uuid",
        "orderNumber": "string",
        "deliveryId": "uuid",
        "trackingId": "string | null",
        "storeProfileId": "uuid",
        "storeUserId": "uuid",
        "storeLocation": {},
        "status": "DECLINED",
        "declinedAt": "2026-01-24T12:34:56.789Z",
        "refundExpected": {
            "amount": "number",
            "currency": "string"
        }
    }
}

order.cancelled

{
    "event": "order.cancelled",
    "data": {
        "orderId": "uuid",
        "orderNumber": "string",
        "trackingId": "string",
        "deliveryId": "uuid",
        "userId": "uuid",
        "profileId": "uuid",
        "refundAmount": "number | null",
        "status": "CANCELLED",
        "canceledAt": "2026-01-24T12:34:56.789Z"
    }
}