# Checkout Rates

Checkout Rates lets you control the shipping options your buyers see at checkout and calculate live shipping rates for a cart. You define the options once as a **configuration**, then request a **quote** whenever you need the rates to show for a given destination and cart.

There are two building blocks:

- **Configuration**: a storefront that groups one or more **delivery options**. Each configuration has a unique `config_id`.
- **Delivery option**: a single choice a buyer can pick — for example, a live-rate service, a flat rate, free shipping, local delivery, or store pickup. Each option has a unique `option_id` within its configuration.


Once a configuration exists, call the [Calculate checkout rates](#calculate-checkout-rates) endpoint with the destination and cart. The response contains one rate per option that produced a price; each rate is an individually retrievable **quote** with its own `quote_id`.

Behind the scenes, the API translates the external identifiers you provide (`carrier_id`, `service_code`) into the carriers and services connected to your account, so you work with the same IDs you use elsewhere in the API.

Despite the similar name, this is a separate feature and is **not** the same functionality as ShipStation's existing [Checkout Rates](https://help.shipstation.com/hc/en-us/articles/360046301731-Send-Rates-to-Store-Checkout-Overview), configured in the ShipStation dashboard. These endpoints provide similar functionality but are not tied to any store and are not an API version of the functionality presented in the ShipStation UI.

## Requirements

- For `live_rate` and `local_delivery` options, you need the `carrier_id` of a connected carrier and a valid `service_code`. [List carriers](/list-carriers) to locate these values.
- An active store on your account. Creating a configuration without one returns a `400 Bad Request` with error code `seller_has_no_active_store`.
- A warehouse (ship-from location) on your account. If you don't have one yet, [Create a warehouse](/apis/openapi/warehouses/create_warehouse) first.
- All requests are authenticated with your API key in the `api-key` header. See [Security & Authentication](/authentication).


## Delivery Option Types

The `type` of an option determines which fields apply.

| Type | Description | Key fields |
|  --- | --- | --- |
| `live_rate` | Real-time carrier rates for the selected services, optionally adjusted by a fee. Can fall back to a fixed or percentage price when rates are unavailable. | `services`, `fee_mode`, `fee_percentage`, `fallback_mode` |
| `flat_rate` | A single fixed shipping price. | `amount`, `currency` |
| `free` | Always shows a price of 0. | *(none)* |
| `local_delivery` | Like `live_rate`, but for local delivery services. Has no fallback. | `services`, `fee_mode`, `fee_percentage` |
| `pickup` | In-store pickup. Usually free, but can charge a prep fee when the cart total is below a threshold. | `amount`, `currency`, `fee_threshold` |


### Fees

For `live_rate` and `local_delivery` options, you can adjust the carrier rate with a fee:

- `fee_mode` — `add` adds to the carrier rate; `subtract` reduces it. Omit `fee_mode` for a pass-through rate.
- `fee_percentage` — the percentage of the carrier rate to add or subtract.


For example, with a carrier rate of `10.00`, `fee_mode: add` and `fee_percentage: 15` produces a shown price of `11.50`.

### Fallbacks

A `live_rate` option can define what to show when live carrier rates cannot be retrieved, using `fallback_mode`:

| Fallback mode | Behavior |
|  --- | --- |
| `dont_show` | Hide the option entirely. |
| `flat_rate` | Show a fixed price from `fallback_rate_amount` and `fallback_rate_currency`. |
| `cart_percentage` | Show `fallback_percentage` of the cart total. |


## Create a Checkout Rates Configuration

**POST /v2/checkout_rates**

Create a configuration together with its initial delivery options and shared settings. The response includes the generated `config_id` and an `option_id` for each option.


```

```

You can also try this request in the browser:

## Get a Configuration

**GET /v2/checkout_rates/:config_id**

Retrieve a single configuration, including all of its options and shared settings.


```

```

## List Configurations

**GET /v2/checkout_rates**

Return an identifying summary of every configuration on your account. Use [Get a Configuration](#get-a-configuration) to retrieve an individual configuration's full details.


```

```

Updating a configuration
A configuration's `shared_settings` are set at creation; there are no operations to update or delete a configuration itself. To change shared settings, create a new configuration. A configuration's delivery options can still be added, updated, and deleted individually at any time.

## Add a Delivery Option

**POST /v2/checkout_rates/:config_id/options**

Add an option to an existing configuration.

Option names must be unique within a configuration. Adding an option whose name already exists returns a `409 Conflict`.


```

```

## Get a Delivery Option

**GET /v2/checkout_rates/:config_id/options/:option_id**


```

```

## Update a Delivery Option

**PUT /v2/checkout_rates/:config_id/options/:option_id**

Replace the configuration of an existing option. Renaming an option to a name already in use returns a `409 Conflict`.


```

```

## Delete a Delivery Option

**DELETE /v2/checkout_rates/:config_id/options/:option_id**

Marks the option as inactive (`is_active: false`) instead of removing it; it still appears in the configuration. Returns `204 No Content`.

## Calculate Checkout Rates

**POST /v2/checkout_rates/:config_id/quotes**

Calculate the rates a buyer should see at checkout for a destination and cart. The response contains one rate per option that produced a price. Each rate is an individually retrievable quote with its own `quote_id`.


```

```

You can also try this request in the browser:

Each rate in the response includes:

| Property | Description |
|  --- | --- |
| `quote_id` | The unique identifier of this rate's quote. Use it with [Get a Quote](#get-a-quote) to retrieve the rate later. |
| `option_id` / `option_name` | The delivery option this rate was produced for. |
| `type` | The delivery option type this rate corresponds to (for example, `live_rate`, `free`). |
| `carrier_id` / `service_code` | The carrier and service for the rate. `null` for options without a carrier (for example, `free`). |
| `final_amount` / `currency` | The price shown to the buyer after fees or fallbacks are applied. |
| `estimated_delivery_days` / `estimated_delivery_date` | Transit estimates, when available. |


## Get a Quote

**GET /v2/checkout_rates/quotes/:quote_id**

Retrieve a previously calculated quote by its `quote_id`. The response contains the single rate that this quote identifies.

Quotes expire
Quotes are retained for a limited time. A request for an expired or unknown `quote_id` returns `404 Not Found`.


```

```

## Validation

The following rules are applied to requests that define delivery options (Create a Configuration, Add a Delivery Option, Update a Delivery Option):

- **`carrier_id` format** — each `carrier_id` must be in the format `se-` followed by digits (for example, `se-1234567`). A value that does not match this format is rejected with a `400 Bad Request`.
- **`carrier_id` must be connected** — a well-formed `carrier_id` that is not connected to your account is rejected as an invalid identifier.
- **`service_code` required** — each service in a `live_rate` or `local_delivery` option must include a non-empty `service_code`. A service code that is not available for the carrier is rejected as an invalid identifier.
- **Unique option names** — option names must be unique within a configuration.


Fields for `services` are only validated for options that use them (`live_rate` and `local_delivery`); options such as `free`, `flat_rate`, and `pickup` do not require services.

## Error Handling

Errors are returned with the standard [error response body](/apis/openapi), which includes a `request_id` and an `errors` array. Each error carries an `error_type`, `error_code`, and `message`; validation errors also include `field_name` and `field_value`.

| Status | When it occurs | `error_code` |
|  --- | --- | --- |
| `400 Bad Request` | A field is missing or malformed — for example, a `carrier_id` in the wrong format, or an unknown `carrier_id`/`service_code`. | `invalid_field_value`, `invalid_identifier` |
| `400 Bad Request` | The account has no active store, which is required to create a configuration. | `seller_has_no_active_store` |
| `404 Not Found` | The `config_id`, `option_id`, or `quote_id` does not exist (or the quote has expired). | *varies* |
| `409 Conflict` | An option name already exists in the configuration. | `identifier_conflict` |
| `500 Internal Server Error` | An unexpected error occurred while processing the request. | *varies* |


## Compatibility

- Checkout Rates uses the same carrier and service identifiers as the rest of the API. The `carrier_id` values come from [List carriers](/list-carriers), and `service_code` values are the same service codes used when [rate shopping](/rate-shopping) and [creating labels](/create-labels).
- Checkout Rates configurations are independent of the [Rates](/rate-shopping) endpoints. A checkout quote is intended for displaying options to a buyer; it does not create a shipment or a label on its own.