# Build a TMS integration

How the Kustom Shipping Assistant calls your TMS for live delivery options in the checkout — the flow from address to Buy, and which endpoints you must build.

The Kustom Shipping Assistant (KSA) puts live delivery choices inside Kustom Checkout: carriers,
pickup points on a map, delivery times, time slots and extras such as a door code or an SMS
notification. None of it is stored at Kustom. Each time the customer's address or cart changes,
Kustom asks the merchant's transport management system (TMS) what it can offer, and when the
customer buys, Kustom reserves the chosen delivery with that same system. This guide is for the
team that builds the TMS side of those calls.

  **Are you a merchant who wants the Shipping Assistant in your checkout?** You don't build any of this. Your TMS provider does, or already has.
  [Shipping options in the checkout](/checkout/shipping/#shipping-assistant) covers what you do: a profile in the Kustom Portal
  and a couple of fields on the order.

Everything below is for the TMS: a transport management system, a transport administrator or
a merchant building a direct integration. You implement a small HTTP API that Kustom calls. You
never call Kustom, and you don't need to know the Checkout API to do it.

## How your TMS fits into a checkout

This is the happy path: a customer enters an address, picks a delivery and pays on the first
try. Each numbered step is a moment in their checkout, the arrows are the calls it causes, and
each step links to the page that covers it.

```mermaid
sequenceDiagram
    actor Customer
    participant Checkout as Kustom
    participant TMS as Your TMS

    critical Customer enters an address
        %% href: /checkout/shipping/shipping-assistant/shipping-options/
        Checkout->>TMS: POST /auth
        Note over Checkout,TMS: Only without a valid token
        TMS-->>Checkout: token
        Checkout->>TMS: POST /shippingoptions
        TMS-->>Checkout: options
        Checkout->>Customer: shows the options
    end

    critical Customer presses Buy
        %% href: /checkout/shipping/shipping-assistant/reserve-shipment/
        Checkout->>TMS: POST /shipment
        TMS-->>Checkout: shipment_id
    end

    critical Purchase completes
        %% href: /checkout/shipping/shipping-assistant/after-purchase/
        Checkout->>TMS: POST /shipment/{shipment_id}/confirm
    end
```

What the happy path leaves out:

- **`POST /auth` comes first only when needed.** Kustom calls it right before its first call to
  your TMS, and whenever you answer `401`. The token is kept per merchant profile and reused
  across checkouts, so most checkouts never call `/auth` at all.
- **Options are asked for more than once.** Kustom asks again when the address or the cart
  changes, and the first request can carry only a country, before the customer has typed
  anything.
- **Pressing Buy is not a purchase.** The payment can still be declined. The customer may then
  change the address, the cart or the delivery and press Buy again, and Kustom
  [updates the reservation](/checkout/shipping/shipping-assistant/reserve-shipment/#updating-with-put)
  it already has with `PUT` instead of creating a second one. A reservation may be updated
  several times, or never confirmed at all.
- **Customers can search for pickup points** near another postal code, which is
  [another `POST /shippingoptions`](/checkout/shipping/shipping-assistant/shipping-options/#pickup-point-searches).
- **You can refuse a reservation.** The customer is asked to
  [pick again](/checkout/shipping/shipping-assistant/reserve-shipment/#refusing-a-reservation).
- **A failed answer to `POST /shippingoptions` shows the customer no error.** The checkout quietly
  switches to the merchant's own fixed list of options, and
  [stays on it](/checkout/shipping/shipping-assistant/errors-and-testing/) for that customer.

## What you must build

Kustom calls one base URL for each merchant profile and appends the paths below to it. There is
no separate URL for authentication.

| Endpoint | You must build it? | Kustom calls it when | Without it |
| --- | --- | --- | --- |
| `POST /auth` | **Yes** | Right before a call to your TMS when Kustom has no token for the merchant profile, and after you answer `401` | Nothing else can be called. Every checkout falls back to the merchant's options |
| `POST /shippingoptions` | **Yes** | The address or cart changes, and on a pickup-point search | Every checkout falls back to the merchant's options |
| `POST /shipment` | **Yes** | The customer presses Buy for the first time | Every purchase is interrupted |
| `PUT /shipment/{shipment_id}` | **Yes**, or answer `404` | The customer presses Buy again after a reservation exists | Answer `404` and Kustom creates a new reservation with `POST /shipment`, leaving the first one orphaned in your system |
| `POST /shipment/{shipment_id}/confirm` | No | The purchase completes | Reservations in your system are never confirmed. The purchase still goes through |

The API reference also lists `GET /shipment/{shipment_id}`. Kustom doesn't call it, so you
don't need to build it.

Inside each response, some fields are required and some are optional with a sensible default.
The page for each call lists them, and marks the fields that are optional on paper but required
for a usable result, such as pickup locations on a pickup-point option.

## Words this guide uses

| Term | What it means here |
| --- | --- |
| Checkout session | One customer's visit to one merchant's checkout. `session_id` in every request identifies it, and stays the same through retries and changes |
| Order lines | The items in the cart. Only physical goods are sent to you |
| Fallback options | A fixed list of delivery options the merchant puts on the order, used when your TMS can't answer |
| Preview options | Options you return before the full address is known, marked `preview: true`. The customer sees them but can't buy with one |
| `shipment_id` | Your identifier for a reservation. The merchant receives it as `tms_reference` on their order, and books against it |
| Minor units | Amounts in the currency's smallest unit, tax included. `4900` is 49.00 |

## Related

- [Shipping options in the checkout](/checkout/shipping/#shipping-assistant) — the merchant's side, and the fixed list used as the fallback
- [Shipping Service Callback API](/api/shipping-service-callback/) — the generated reference for all six operations
- [Shipping partners](/partners/shipping-partners/) — the TMS providers that already have a connection
