# Timeouts, fallback and testing your TMS

What the customer sees when a Shipping Assistant call to your TMS fails or times out, how fallback works, and how to test your integration in playground.

Your TMS sits in the middle of someone's purchase, so Kustom is built to keep the checkout working
when your TMS doesn't. That makes failures quiet: a broken `POST /shippingoptions` doesn't show
the customer an error, it swaps your options for the merchant's own. This page lists what each
failure does, the time limits, and how to test against playground before a merchant goes live.

## What each failure does

| What happens | What the customer sees |
| --- | --- |
| `POST /shippingoptions` times out, answers anything but `200`, or returns a body Kustom can't use | The merchant's fallback options. **For the rest of that checkout**: Kustom stops calling you for it |
| `POST /auth` fails, or a call still gets `401` after a fresh token | Same as above |
| `POST /shippingoptions` returns an empty list | "We cannot ship to the given address". Not a fallback: the customer changes the address, and Kustom asks again |
| `POST /shipment` or `PUT /shipment/{shipment_id}` fails in any way | The purchase stops, Kustom asks for options again and the customer picks again. See [Refusing a reservation](/checkout/shipping/shipping-assistant/reserve-shipment/#refusing-a-reservation) |
| That new `POST /shippingoptions` fails too | The merchant's fallback options |
| `POST /shipment/{shipment_id}/confirm` fails | Nothing. The purchase is already complete |

Fallback is a checkout with no TMS at all. The customer chooses from the fixed list the merchant
put on the order, and if the merchant sent no list, buys with a delivery address and no delivery
option. Either way, no reservation reaches you for that purchase, so the merchant has to book it
some other way. Every fallback is a lost booking for you and extra work for them.

"A body Kustom can't use" is broader than malformed JSON. One unknown value anywhere rejects the
whole response — the [list is on the options page](/checkout/shipping/shipping-assistant/shipping-options/#response).
Validate your own responses against it before you go live.

## Time limits

Kustom gives each call **8 seconds** by default, and less for some integrations. Past that, the
call has failed. A customer is watching a spinner while `POST /shippingoptions` runs, so aim
for well under a second there. `POST /shipment` runs while they wait after pressing Buy, so the
same goes for it.

Kustom repeats a call once, a second later, after some network errors. That's why the same
`POST /shipment` can arrive twice — see
[Make `POST /shipment` safe to repeat](/checkout/shipping/shipping-assistant/reserve-shipment/#make-post-shipment-safe-to-repeat).

If a large share of calls to your host fail in a short time, Kustom stops calling it for a few
seconds, and every checkout in that window falls back. A slow dependency that makes some calls
time out can take down calls that would have succeeded.

## Test in playground

Kustom's playground environment is separate from production, with its own merchant accounts.
Build against it first.

1. **Try your endpoints in [Shipwreck](https://shipwreck.playground.kustom.co/)**, Kustom's test
   tool for TMS integrations. It calls your API the way the checkout does and shows how your
   options render in the shipping selector.
2. **Connect a playground merchant.** A playground merchant account adds a Shipping Assistant
   profile pointing at your TMS, with an identifier and key you issue — see
   [Shipping options in the checkout](/checkout/shipping/#shipping-assistant). No playground
   merchant to test with? Create one with **Get playground access** at the top of this page, or
   at [portal.playground.kustom.co](https://portal.playground.kustom.co/onboarding).
3. **Walk through a real checkout.** Enter an address, change it, search for a pickup point, press
   Buy, and complete the purchase. Check that each call from the
   [flow](/checkout/shipping/shipping-assistant/#how-your-tms-fits-into-a-checkout) reaches you
   and that your `shipment_id` arrives on the order as `tms_reference`.
4. **Test the failures.** Answer `401` once and watch Kustom re-authenticate. Refuse a
   reservation with a `failure_reason`. Make `PUT /shipment/{shipment_id}` answer `404`.
5. **Check the merchant's fallback.** A customer email containing `+fallback`, such as
   `jane+fallback@example.com`, makes playground skip your TMS and show the fallback options, so
   the merchant can see what their customers get when you're unavailable.

## Before you go live

- Every response validates against the lists on the
  [options page](/checkout/shipping/shipping-assistant/shipping-options/), for every carrier and
  type you'll return.
- `POST /shipment` returns the same `shipment_id` when it's repeated for a `session_id`.
- `PUT /shipment/{shipment_id}` replaces the reservation rather than adding one.
- `POST /shippingoptions` answers inside a second under your expected load.
- Each merchant has their own Identifier and Key, and you can revoke one without the others.
- You log `Klarna-Correlation-Id`, so Kustom support can find a call you're asking about.

## Related

- [Build a TMS integration](/checkout/shipping/shipping-assistant/) — the flow and what you must build
- [Shipping options in the checkout](/checkout/shipping/#basic-shipping-options) — what the merchant's fallback list looks like
- [Shipping Service Callback API](/api/shipping-service-callback/)
