---
title: "Read a purchase turn that was still running"
method: GET
path: "/get-purchase-turn"
tags: ["cards"]
---

# Read a purchase turn that was still running

`GET /get-purchase-turn`

## Request

- Base URL: `https://laso.finance`
- URL: `https://laso.finance/get-purchase-turn`
- Auth: API key in header `Authorization`

Reads back a turn from `POST /buy-with-saved-card` that came back `state: running`. Poll every few seconds until `state` is `done` or `failed`; the response has the same shape as the POST.

A `failed` confirm may still have placed the order. Read `GET /get-purchase-conversation` before sending it again.

## Query parameters

- `turn_id` string, required

## Response `200`

The turn.

- object
  - `turn_id` string: This turn's id. Poll `GET /get-purchase-turn` with it while `state` is `running`.
  - `state` 'running' | 'done' | 'failed': `running` means the turn is still talking to the merchant; the fields below appear once it is `done`.
  - `created_at` integer: Milliseconds since the epoch.
  - `conversation_id` string: Send it back on every follow-up and on the confirm.
  - `status` 'needs_input' | 'awaiting_approval' | 'in_progress' | 'order_placed' | 'declined' | 'conflict': What to do next. `needs_input`: a question or a cart waiting on a confirm. `awaiting_approval`: send `approval_url` to the holder, then repeat the same confirm. `in_progress`: the order is already being placed; read `GET /get-purchase-conversation` instead of confirming again. `order_placed`. `declined`: see `decline_code`. `conflict`: nothing ran, see `error_code` and confirm the fresh cart's hash. Never branch on `reply`.
  - `reply` string: The shopping assistant's turn as prose, ready to show the holder.
  - `cart` object, nullable: The most recently shown cart.
    - `merchant` string: Merchant id, e.g. `retail` or `doordash`.
    - `merchant_name` string: Display name, e.g. `Amazon`.
    - `items` object[]
      - `name` string
      - `quantity` integer
      - `price_cents` integer, nullable
      - `product_id` string, nullable: The merchant's id for the line, usually its product link.
    - `fees_cents` integer: All fees combined, including the service fee.
    - `tip_cents` integer
    - `total_cents` integer: The all-in total to show the account holder.
    - `approved_ceiling_cents` integer, nullable: The most the merchant may charge once final tax and shipping settle. This is what the holder's approval covers; any unused amount is released. Null when the merchant prices the cart exactly.
    - `hash` string: Identity of exactly this cart. Send it back as `confirm` to place it.
  - `carts` object[]: Every open cart in the conversation, oldest first.
    - `merchant` string: Merchant id, e.g. `retail` or `doordash`.
    - `merchant_name` string: Display name, e.g. `Amazon`.
    - `items` object[]
      - `name` string
      - `quantity` integer
      - `price_cents` integer, nullable
      - `product_id` string, nullable: The merchant's id for the line, usually its product link.
    - `fees_cents` integer: All fees combined, including the service fee.
    - `tip_cents` integer
    - `total_cents` integer: The all-in total to show the account holder.
    - `approved_ceiling_cents` integer, nullable: The most the merchant may charge once final tax and shipping settle. This is what the holder's approval covers; any unused amount is released. Null when the merchant prices the cart exactly.
    - `hash` string: Identity of exactly this cart. Send it back as `confirm` to place it.
  - `catalog` object[]: The last product search. Empty on a turn that did not search again, so keep the previous one.
    - `product_id` string: The merchant's product link.
    - `name` string, nullable
    - `price_cents` integer, nullable
    - `image_url` string, nullable
  - `unmatched` object[]: Things asked for that did not make it into a cart, with a reason. Show these rather than guessing from `reply`.
    - `merchant` string
    - `requested` string
    - `reason` 'not_found' | 'unavailable'
    - `detail` string, nullable
  - `order_id` string, nullable: Set when this turn placed an order.
  - `decline_code` string, nullable: The machine reason behind `declined`, e.g. `items_unavailable`.
  - `approval_url` string, nullable: Send to the holder when `status` is `awaiting_approval`. Never open it yourself.
  - `charge_status` 'none' | 'confirming' | 'settled' | 'unknown' | 'null', nullable: Whether money moved: `none`, `confirming`, `settled`, or `unknown` (do not retry; read the conversation).
  - `card_last4` string, nullable: The saved card that paid, for naming it to the holder.
  - `error_code` string, nullable: On `conflict`: `cart_changed`, `turn_in_progress`, `delivery_address_changed`, or `delivery_address_bound_after_cart`.
  - `error` string: Present when `state` is `failed`.
  - `note` string: The next step.

## Other responses

- `400`: `turn_id` is missing, or no card is saved on this account yet.
- `404`: No such turn on this account.

---

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