# Handle merchant callbacks

> Choose the request and response format required by your Bolt integration.

Source: https://help.boltapp.com/api-reference/merchant-callback/how-bolt-calls-you

A callback asks your server for information used during checkout. A webhook reports an event that already happened. Confirm your division's integration type before implementing a callback handler.

## Which URL Bolt calls [#which-url-bolt-calls]

In the Universal Merchant API flow, Bolt can use an event-specific URL or fall back to the division's Universal Merchant API URL. Dispatch requests using the top-level `event` field. Register the URLs needed by your integration under **Administration > Developers > API**.

Plugin integrations use their platform's callback handlers. For example, the plugin `cart.update` flow requires the specific update-cart URL; it does not use the universal fallback.

A stored Universal Merchant API URL alone is not proof that the division uses the universal format. Confirm the configured integration with Bolt if you are unsure.

## Request formats [#request-formats]

Universal requests wrap the event body in `data`. A cart-update request has this structure:

```json
{
  "event": "cart.update",
  "data": {
    "type": "cart.update",
    "order_reference": "order_1001",
    "discount_codes_to_add": ["SAVE20"]
  }
}
```

Plugin cart-update requests carry those body fields at the root. See [cart.update](/api-reference/merchant-callback/cart-update) for response requirements and [Universal callback conventions](/api-reference/merchant-callback/conventions) for other events.

## The response envelope depends on your integration type [#the-response-envelope-depends-on-your-integration-type]

For Universal Merchant API callbacks, include the event and put the callback-specific response in `data`:

```json
{
  "event": "cart.update",
  "status": "success",
  "data": {
    "order_create": {
      "cart": {
        "order_reference": "order_1001",
        "currency": "USD",
        "total_amount": 800,
        "items": [
          { "reference": "item_1", "name": "Download", "quantity": 1,
            "unit_price": 1000, "total_amount": 1000, "type": "digital" }
        ],
        "discounts": [
          { "amount": 200, "code": "SAVE20", "description": "20 percent off",
            "reference": "SAVE20", "discount_category": "coupon" }
        ]
      }
    }
  }
}
```

For the plugin cart-update format, place `order_create` at the root alongside `status`, without the `data` wrapper. Preserve the fields required by your platform and cart.

An HTTP 200 response does not establish that the payload is valid. Check the event-specific contract instead of trying different envelopes until one appears to work.

## Verify incoming requests [#verify-incoming-requests]

Verify the base64-encoded HMAC-SHA256 signature in `X-Bolt-Hmac-Sha256` using the signing secret and the exact raw request body. Use a constant-time comparison. For GET callbacks, check the query-string signing rules in [Callback conventions](/api-reference/merchant-callback/conventions#verifying-the-request-came-from-bolt).

During signing-secret rotation, validate the active or pending signature against its corresponding secret. See [Verify webhooks](/api-reference/guides/verify-webhooks) for implementation examples.

## Handle failures [#handle-failures]

Failure behavior depends on the callback and division settings. A missing `order_create` fails a cart update. Some abnormal `order.create` failures can allow payment processing to continue, so monitor your handler and reconcile orders with payments.

Use the error shape documented for each event. See [Callback failure behavior](/api-reference/merchant-callback/conventions#when-your-endpoint-fails).

If a request fails or never arrives, check the callback URL and inbound traffic rules. Contact [support](/support) with the environment, division public ID, timestamp, order reference, and redacted request and response. Never send API keys or signing secrets.
