WHCC sends webhook notifications in one of two payload formats, depending on when your integration was set up. This page documents the legacy V1 format. If your integration receives JSON request bodies, see Webhook Types for the V2 format instead.
If you are not sure which version your integration receives, check the Content-Type header on an incoming webhook request. V1 is application/x-www-form-urlencoded. V2 is application/json.
V1 webhook requests are sent with Content-Type: application/x-www-form-urlencoded. The body is a single query-string-style line with the following fields, always in this order:
1
Message=…&EntryId=…&ConfirmationId=…&SequenceNumber=…&Reference=…&EventId=…&json=…
| Field | Meaning |
|---|---|
Message |
Human-readable summary of the event. Format varies by EventId; see examples below. |
EntryId |
The entry identifier from your original order request. |
ConfirmationId |
WHCC's identifier for the confirmation this order belongs to. Not unique per order — split orders share it. Use it together with SequenceNumber and the event type as your deduplication key. |
SequenceNumber |
The sequence number from your original order request. When WHCC splits an order, each resulting order gets a suffixed value (for example "1" and "1.2"), which is what distinguishes orders sharing a ConfirmationId. |
Reference |
The reference value from your original order request. |
EventId |
The event, one of: order.received, order.shipped, image.upload. That is the complete list — V1 integrations never receive order-cancellation webhooks. Cancellations are V2-only. If you need them, migrate to V2. |
json |
A JSON-serialized copy of the same fields, structured for programmatic parsing. |
json is URL-encodedThe json field's value is properly percent-encoded, as you'd expect for a form-urlencoded body. The other top-level fields (Message, EntryId, ConfirmationId, SequenceNumber, Reference, EventId) are not encoded — they are written out with literal spaces, colons, semicolons, and braces. If Message itself contains an unescaped & or = (for example, an embedded URL with a query string), a naive form parser that blindly splits the whole body on & and = will misparse it.
Parse the json field for reliable, structured access to every field on that same notification. Treat Message as a display string only, and don't rely on splitting the raw body around it.
order.receivedSent when WHCC accepts an order.
1
Message=Order Received at WHCC;OrderNumber: 99000214&EntryId=SP-20481193&ConfirmationId=72e6ebbb-b29f-4fb6-ae2b-03bd9c4c1c34&SequenceNumber=1&Reference=SP-20481193 Prints&EventId=order.received&json=%7B%22EventId%22%3A%22order.received%22%2C%22Message%22%3A%7B%22OrderNumber%22%3A%2299000214%22%2C%22Status%22%3A%22Received%22%7D%2C%22ConfirmationId%22%3A%2272e6ebbb-b29f-4fb6-ae2b-03bd9c4c1c34%22%2C%22EntryId%22%3A%22SP-20481193%22%2C%22Reference%22%3A%22SP-20481193+Prints%22%2C%22SequenceNumber%22%3A%221%22%7D
The json field, decoded:
1
2
3
4
5
6
7
8
9
10
11
{
"EventId": "order.received",
"Message": {
"OrderNumber": "99000214",
"Status": "Received"
},
"ConfirmationId": "72e6ebbb-b29f-4fb6-ae2b-03bd9c4c1c34",
"EntryId": "SP-20481193",
"Reference": "SP-20481193 Prints",
"SequenceNumber": "1"
}
order.shippedSent when an order (or part of an order) ships.
1
Message=Order has shipped;OrderNumber: 99000530;Carrier: USPS;ShipDate: 6/2/2026 10:14:27 AM CST;Tracking: {9400111899561234567890}&EntryId=SP-20481594&ConfirmationId=4853ef91-2f6c-40e9-8258-33910a511467&SequenceNumber=1&Reference=SP-20481594 Prints&EventId=order.shipped&json=%7B%22EventId%22%3A%22order.shipped%22%2C%22Message%22%3A%7B%22Carrier%22%3A%22USPS%22%2C%22OrderNumber%22%3A%2299000530%22%2C%22Status%22%3A%22Shipped%22%2C%22ShipDate%22%3A%226%2F2%2F2026+10%3A14%3A27+AM+CST%22%2C%22Tracking%22%3A%22%5B%5C%229400111899561234567890%5C%22%5D%22%7D%2C%22ConfirmationId%22%3A%224853ef91-2f6c-40e9-8258-33910a511467%22%2C%22EntryId%22%3A%22SP-20481594%22%2C%22Reference%22%3A%22SP-20481594+Prints%22%2C%22SequenceNumber%22%3A%221%22%7D
The json field, decoded (note that Tracking is itself a JSON array, serialized to a string):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"EventId": "order.shipped",
"Message": {
"Carrier": "USPS",
"OrderNumber": "99000530",
"Status": "Shipped",
"ShipDate": "6/2/2026 10:14:27 AM CST",
"Tracking": "[\"9400111899561234567890\"]"
},
"ConfirmationId": "4853ef91-2f6c-40e9-8258-33910a511467",
"EntryId": "SP-20481594",
"Reference": "SP-20481594 Prints",
"SequenceNumber": "1"
}
image.uploadSent when WHCC finishes retrieving your submitted image assets — whether or not anything went wrong. Status tells you which happened, and is the only thing that distinguishes the two cases:
Status carries the recorded error text followed by AssetPath : and the asset URL, as shown below. The most common is the missing-asset condition, which corresponds to the 400.02 error on V2 — but it is not the only one. Other conditions appear here too, including hash mismatches that cancel the order.Status is the literal string "Assets Downloaded" (described below).Parse Status as free text and do not assume a single error type. Do not treat the arrival of an image.upload webhook as meaning something failed.
1
Message=Image is missing on consumer site. AssetPath : http://images.example-partner.com/Rendering/Full?orderProductId=999000417&h=8021&EntryId=30887421&ConfirmationId=45628cc7-134e-46c3-9e5e-fe0d1a9f55bd&SequenceNumber=14205817&Reference=30887421-701&EventId=image.upload&json=%7B%22EventId%22%3A%22image.upload%22%2C%22Message%22%3A%7B%22Status%22%3A%22Image+is+missing+on+consumer+site.+AssetPath+%3A+http%3A%2F%2Fimages.example-partner.com%2FRendering%2FFull%3ForderProductId%3D999000417%26h%3D8021%22%7D%2C%22ConfirmationId%22%3A%2245628cc7-134e-46c3-9e5e-fe0d1a9f55bd%22%2C%22EntryId%22%3A%2230887421%22%2C%22Reference%22%3A%2230887421-701%22%2C%22SequenceNumber%22%3A%2214205817%22%7D
The json field, decoded — and the example above of why you should parse it instead of the raw body: the AssetPath URL's own &h=8021 query parameter would be mistaken for a top-level form field by a naive &-splitting parser.
1
2
3
4
5
6
7
8
9
10
{
"EventId": "image.upload",
"Message": {
"Status": "Image is missing on consumer site. AssetPath : http://images.example-partner.com/Rendering/Full?orderProductId=999000417&h=8021"
},
"ConfirmationId": "45628cc7-134e-46c3-9e5e-fe0d1a9f55bd",
"EntryId": "30887421",
"Reference": "30887421-701",
"SequenceNumber": "14205817"
}
The same image.upload event is also sent with Status set to the literal string "Assets Downloaded". This means the asset-download step finished with no errors recorded against that notification. It is not a follow-up to an earlier failure, and it does not indicate that a previously missing asset has since been retrieved — the two are unrelated events. Do not treat "Assets Downloaded" as clearing a failure you were told about earlier.
Only the first error is reported. When several assets fail on one order, the image.upload payload names just one of them. Fixing the asset in the message does not mean the order is clear — re-check every asset you submitted.
Delivery, Retries & Idempotency covers the retry schedule and why your deduplication key must be (ConfirmationId, SequenceNumber, event type).
Security and Signatures describes how V1 signatures differ from V2.