The request envelope
Bolt sends every event as an envelope ofevent and data, and the payload for that event sits inside data:
discount.code.apply, which is not a real event:
The response envelope
Your response uses the same envelope. Echo theevent you are answering, set a status, and put the body inside data:
When your endpoint fails
A rejected or failing response does not always stop the checkout. What happens depends on your division, and the custom cart default is the quiet one:
For a custom cart this means a broken callback produces successful payments with no matching orders, and nothing in the shopper’s experience indicates a problem. Alert on your own callback error rate rather than expecting checkout to surface it.
To fail on purpose, set
status to failure and return a code. The field differs by event, so check the event’s reference page:
Amounts and currency
The same field name can be a number or an object depending on which event you are handling. The rule is that events carrying a full cart snapshot use the expanded form, and events carrying a working cart use plain integers:
Amounts are always in the currency’s minor units, so
41200 is $412.00.
Type your inbound carts per event rather than sharing one cart model across all of them. Reusing a single strict model is the most common cause of a callback returning an error on one event while working on the others.
Delivery option signatures
Shipping options, pickup options, and ship to store options all carry asignature field. Despite the name it is not a cryptographic value and Bolt does not verify it. It forms part of the cache key for the tax result attached to an option.
Give each option a value that is stable for as long as the option means the same thing, and change it whenever the option changes in a way that should invalidate its tax. Omitting it disables tax caching for that option rather than failing the request.
Verifying the request came from Bolt
Every callback is signed. Compute the base64 encoded HMAC SHA-256 of the raw request body using your signing secret, then compare it to theX-Bolt-Hmac-Sha256 header:
TypeScript
GETendpoints, such as the OAuth login callback, sign the query string rather than a body.- While a signing secret is being rotated, Bolt also sends
X-Bolt-Hmac-Sha256-Pending, holding the same body signed with the incoming secret. Accept the request if either header matches, so that verification keeps working across the rotation.