---
title: "Create a cart from inventory"
method: POST
path: "/carts/inventory"
tags: ["Checkout Carts"]
---

# Create a cart from inventory

`POST /carts/inventory`

## Request

- Base URL: `https://api.ekho.com`
- URL: `https://api.ekho.com/carts/inventory`
- Auth: HTTP bearer

Creates a checkout cart for the account bound to the token and returns it with a `checkout_url` the buyer can be sent to. The account that owns the cart is resolved server-side from the token, so the request carries no owner identifiers. Buyer prefill is optional. The cart holds one dealer unit, named by `inventory_id`. The body takes no vehicle list, no accessory field, and no preorder flag, because a unit is a specific vehicle that already exists rather than a configuration to build. To sell a vehicle to be built instead, use `POST /carts/build-to-order`.

## Request body

- CreateInventoryCartRequest
  - `inventory_id` string, required: The inventory unit being sold. One unit per cart.
  - `prefill_cart` CartPrefill
    - `buyer` object
      - `full_name` string
      - `email` string, email
      - `phone` string
      - `address` CartPrefillAddress: Buyer address. The state sets where the vehicle is registered.
        - `line1` string
        - `line2` string
        - `city` string
        - `state` string: Two-letter state code.
        - `zip` string
  - `cancel_redirect_url` string: URL the buyer is redirected to if they cancel checkout.
  - `metadata` object: Free-form metadata carried through to the cart, and on to the order and its vehicles. Stored as written, so a nested object or an array needs no JSON encoding and reads back in the shape it was sent. At most 100 object keys and 2 levels of object nesting, and no array may hold another array.
  - `promo_codes` string[]: Promotion codes, matched against the promotions published for your account. A code matching none is skipped rather than failing the request. At most 10. Matching runs after the cart is written, so a `validate_only` request reports nothing about them.
  - `validate_only` boolean: When true, the request is checked as a real one would be, then stops: no cart is created. A request that would have succeeded answers 200 with `{"validate_only": true}`; one that would have failed answers the same error. Reserves nothing, so a unit can still sell between a passing check and the create.

## Response `200`

A `validate_only` request passed. No cart was created.

- object
  - `data` CartValidation, required
    - `validate_only` true, required: Always true. Marks a response that validated a cart without creating one.
    - `dropped_accessories` DroppedAccessory[], required: Accessories named in the request that the cart was built without. Always present, empty when every one was added. A non-empty list is the only signal that the cart is priced for less than was asked for, so check it before treating the response as a complete order. Reported here for the cart that would be created.
      - `id` string, required: The accessory id exactly as the request wrote it.
      - `reason` 'not_found' | 'invalid_id' | 'inactive' | 'incompatible', required: Why it was left out. `not_found`: no accessory has that id. `invalid_id`: the id is malformed. `inactive`: it exists but is not sold. `incompatible`: it is not sold for this vehicle or manufacturer.

## Other responses

- `201`: The cart was created.
- `400`: The request could not create a cart.
- `401`: Authentication is missing or invalid.
- `403`: The token lacks `carts:write`.
- `429`: The rate limit has been exceeded.
- `500`: An unexpected error occurred.

## Changes

- **2026-10-20** `efe485119dd7`: 2 info
  - added the required property `data/dropped_accessories` to the response with the `200` status
  - added the required property `data/dropped_accessories` to the response with the `201` status
- **2026-10-19** `87f98453866f`: 1 info
  - added the new optional request property `promo_codes`
- **2026-10-15** `223234fa2ded`: 2 breaking
  - the `metadata/additionalProperties/` request property type changed from `string` to no type
  - the `data/metadata/additionalProperties/` response's property type changed from `string` to no type for status `201`
- **2026-09-26** `5fe44535e1ab`: 2 info
  - added the new optional request property `validate_only`
  - added the success response with the status `200`
- **2026-09-18** `78c545d96a34`: 15 warning
  - added the new `external_id_in_use` enum value to the `code` response property for the response status `400`
  - added the new `external_id_in_use` enum value to the `code` response property for the response status `401`
  - added the new `external_id_in_use` enum value to the `code` response property for the response status `403`
  - added the new `external_id_in_use` enum value to the `code` response property for the response status `429`
  - …11 more

[Operation history](https://skmtc.dev/ekho/apis/ekho-api/changes/carts/inventory/post.md)

---

[API](https://skmtc.dev/ekho/apis/ekho-api.md) · [All operations](https://skmtc.dev/ekho/apis/ekho-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ekho/apis/ekho-api/revisions/efe485119dd7?raw)
