Use POST https://app.ship.com/public/webhook to register the URL that receives tracking notifications for your account. One webhook URL is stored per account, and re-POSTing replaces the existing registration. Use GET /public/webhook to view your current registration and signing secret, and DELETE /public/webhook to remove it. The URL must be an absolute http(s) address on a public host.
Successful Response Example
{
"success": true,
"result": {
"url": "string",
"signingSecret": "whsec_..."
}
}
Error Response Example
{
"success": false,
"error": "string"
}
GET /public/webhook
Returns your current registration, in the same shape as the successful response above. If a URL is registered but no signing secret exists yet, this call creates and returns one, so integrations registered before signing was introduced can adopt signature verification without re-registering their URL.
DELETE /public/webhook
Removes the registered URL and returns {"success": true}. Your signing secret is kept, so a later re-registration resumes with the same secret.
Webhook Delivery
The webhook fires once per order, about 5 minutes after a shipping label is purchased for it. It does not fire on later carrier scan events (in transit, delivered). If your endpoint responds with a non-2xx status or is unreachable, delivery is retried with growing backoff (5 minutes times the attempt number, capped at 60 minutes) for up to roughly 10 attempts. Use EventId to deduplicate, since retries re-send the same event.
Note: the webhook payload uses PascalCase field names, unlike API responses, which are camelCase.
{
"EventId": 12345678,
"EventType": "label_printed",
"Id": 987654,
"InvoiceNumber": "string",
"OrderStatus": "Label Printed",
"FirstName": "string",
"LastName": "string",
"Email": "string",
"Phone": "string",
"Address1": "string",
"Address2": "string",
"Address3": "string",
"City": "string",
"State": "string",
"Zip": "string",
"Country": "string",
"Total": 0.00,
"SalesTax": 0.00,
"Handling": 0.00,
"Subtotal": 0.00,
"Shipping": 0.00,
"Weight": 0.00,
"Discount": 0.00,
"Shipment": {
"ShipDate": "date",
"ShippingMethod": "string",
"ShippingCost": 0.00,
"TrackingNumber": "string",
"TrackingURL": "string",
"ShippingLabelURL": "string"
},
"Items": [
{
"Id": 0,
"ItemCode": "string",
"UPC": "string",
"Price": 0.00,
"Quantity": 0
}
]
}
Verifying Signatures
Every delivery includes an X-Ship-Event-Id header. Once your account has a signing secret, deliveries also include X-Ship-Timestamp (unix seconds) and X-Ship-Signature. To verify: concatenate the timestamp, a period, and the raw request body; compute HMAC-SHA256 using your signing secret as the key; then compare the lowercase hex digest against the value after "v1=" in X-Ship-Signature.
X-Ship-Event-Id: 12345678
X-Ship-Timestamp: 1786830000
X-Ship-Signature: v1=3f7d9a2c1b45e6...