About
Use the Merchant Callback API to handle shipping and tax information for your orders. This is required for multi-step checkout.
The envelope, verification, and amount encoding are the same for all three endpoints below and are covered in Merchant Callback conventions. Note that the carts on these events use plain integer amounts, not the object form used by order.create.
Shipping API
- Implement the Shipping API endpoint on your server.
- Verify the authenticity of the request.
- Respond to Bolt’s
order.shippingPOST request from your Merchant Callback API.
Bolt sends the shopper’s address and the current cart:
{
"event": "order.shipping",
"data": {
"order_token": "9c8e1f3a2b7d4e5f6a0b1c2d3e4f5a6b",
"shipping_address": {
"street_address1": "123 Baker Street",
"locality": "San Francisco",
"region": "California",
"postal_code": "94550",
"country_code": "US",
"email": "jane@example.com",
"phone": "+14155550199"
},
"cart": {
"display_id": "displayid_100",
"order_reference": "order_100",
"currency": "USD",
"total_amount": 41200,
"items": [
{ "reference": "sku-mug-01", "name": "Bolt Coffee Mug", "unit_price": 20150, "total_amount": 40300, "quantity": 2 }
]
}
}
}
Return the options you want the shopper to choose from:
{
"event": "order.shipping",
"status": "success",
"data": {
"shipping_options": [
{ "service": "Standard", "cost": 500, "reference": "std", "signature": "std-v1" },
{ "service": "Express", "cost": 1500, "reference": "exp", "signature": "exp-v1", "default": false }
]
}
}
cost is in the currency’s minor units. For signature, see delivery option signatures.
PHP Example
<?php
require(dirname(__FILE__) . '/init_example.php');
$hmacHeader = @$_SERVER['HTTP_X_BOLT_HMAC_SHA256'];
$signatureVerifier = new \BoltPay\SignatureVerifier(
\BoltPay\Bolt::$signingSecret
);
$requestJson = file_get_contents('php://input');
if (!$signatureVerifier->verifySignature($requestJson, $hmacHeader)) {
throw new Exception("Failed HMAC Authentication");
}
// The payload for every event is nested under `data`.
$shippingAddress = json_decode($requestJson)->data->shipping_address;
$response = [
'event' => 'order.shipping',
'status' => 'success',
'data' => [
'shipping_options' => [
['service' => 'Standard', 'cost' => 500, 'reference' => 'std', 'signature' => 'std-v1'],
],
],
];
header('Content-Type: application/json');
http_response_code(200);
echo json_encode($response);
The other two endpoints verify the request identically. Only the payloads differ.
Tax API
The Tax API endpoint is called after a shopper has chosen a shipping option.
- Implement the Tax API endpoint on your server.
- Verify the authenticity of the request.
- Respond to Bolt’s
order.taxPOST request from your Merchant Callback API.
The request is the shipping request plus the option the shopper picked, echoed back to you under shipping_option:
{
"event": "order.tax",
"data": {
"order_token": "9c8e1f3a2b7d4e5f6a0b1c2d3e4f5a6b",
"shipping_address": { "postal_code": "94550", "country_code": "US" },
"shipping_option": { "service": "Standard", "cost": 500, "reference": "std", "signature": "std-v1" },
"cart": { "order_reference": "order_100", "currency": "USD", "total_amount": 41200 }
}
}
Respond with the tax for the order:
{
"event": "order.tax",
"status": "success",
"data": {
"tax_result": {
"subtotal_amount": 900
},
"items": [
{ "amount": 900 }
],
"taxes_included": false
}
}
tax_result.subtotal_amount is the total tax for the order in minor units. It is not a rate, and it is not the sum of separate subtotal and shipping rates. Per item tax, if you calculate it, goes in the top level items array.
WARNING
Set taxes_included to true only if your cart amounts already contain tax. When it is true, Bolt treats the tax figures as display only and does not add them to the total. Sending true for a tax exclusive cart undercharges the shopper, and sending false for a tax inclusive cart charges tax twice.
Shipping & Tax API
WARNING
The combined Shipping & Tax endpoint will eventually be deprecated. Bolt recommends using the new, decoupled endpoints for Shipping and Tax.
- Implement the shipping_and_tax Merchant Callback API on your server.
- Verify the authenticity of the request.
- Respond to Bolt’s
order.shipping_and_taxPOST request from your Merchant Callback API.
This endpoint returns shipping options and tax together. Its tax_result is a different, wider object than the one the decoupled Tax endpoint accepts:
{
"event": "order.shipping_and_tax",
"status": "success",
"data": {
"currency": "USD",
"shipping_options": [
{ "service": "Standard", "cost": 500, "reference": "std", "signature": "std-v1" }
],
"tax_result": {
"subtotal_amount": 900,
"rate_subtotal": 0,
"rate_shipping": 0,
"items": [{ "rate": 0, "amount": 900 }]
}
}
}
subtotal_amount carries the tax. The rate fields exist on this shape but Bolt does not read them from your response, and the legacy rate and amount fields on tax_result are deprecated. This difference between the two endpoints is one more reason to prefer the decoupled ones.
Test the Endpoint
Use the following steps to test your Shipping and Tax API implementation:
- Navigate to your store.
- Open Bolt Checkout, enter an address, then continue to Shipping.
- Bolt should hit your
/shipping_and_taxendpoint. - The shipping and tax options from your response should appear in the Bolt Checkout modal.
- Bolt should hit your
- Try all shipping options.
- Ensure that the price of shipping and tax on the cart updates accurately.
Errors & Troubleshooting
To respond with specific errors in merchant api responses visit the error codes documentation.