Skip to main content
GET /v2/merchant/shops/:shopId/abandoned-carts/:cartId returns the full report-ready envelope for one abandoned cart: line items (with thumbnails, SKUs, qty × unit price, line total), customer contact, subtotal in the cart’s currency, the recovery-event timeline, and the recovery token (until the cart is recovered).
This endpoint pairs with the merchant list + stats endpoints. The list returns row summaries; this endpoint returns the drawer-ready detail. Use this when a merchant clicks a row to see what was actually in the cart and how the recovery has progressed.

When to use this

  • The merchant dashboard renders a cart-details drawer when a merchant clicks a row in the abandoned-carts list
  • A future details page wants the full cart payload + recovery timeline in one round-trip
  • A pre-resend preview surface needs to confirm the contents before re-sending the recovery email

Authentication

Merchant JWT (PRODUCER role) plus shop-ownership enforced server-side by the shared MerchantShopScope guard. The JWT-bound shopId claim must equal the :shopId path parameter. Cross-shop access returns 404 — never 403 — to avoid leaking the existence of :cartId to an enumeration attacker.

Request

Curl example

Response (200)

Field reference

Money fields are MAJOR units

Unlike the list endpoint which serializes cartTotalCents (cents, integer minor units), the details endpoint returns subtotal, unitPrice, and lineTotal in MAJOR units of currency. The backend’s projection layer converts once at the boundary using a zero-decimal-currency table (e.g. JPY/KRW have no fractional unit; USD/EUR have 2 decimals). The client can pass the values straight into Intl.NumberFormat({ style: 'currency', currency }) without dividing by 100. This contract diverges from the list endpoint intentionally — the list optimizes for the table cell where minor-unit integers avoid float drift across aggregates; the drawer endpoint pre-formats the merchant-friendly value so the UI doesn’t need to know the currency-decimals table.

Recovery token redaction

The backend includes recoveryToken in the response only while recoveredAt === null. After the checkout-success chokepoint flips the row, the token is operationally useless (the cart cannot be re-recovered) and exposing it widens the leak surface. The merchant dashboard hides the “copy recovery link” CTA whenever the field is null — defense-in-depth even though the BE already redacts.

Recovery event channels

Error responses

The list + stats endpoints documented on the merchant page are migrating from a 403 to a 404 posture on cross-shop access to match this endpoint (tracked in droplinked-backend PR #1980). Once that lands, all three endpoints will share the unified 404 + abandoned_cart_not_found body.

Drawer-style flow