# After the sale over UCP

> Orders, files a shopper bought, cancellations, returns, buying again, errands, gift cards, subscriptions and terms, through UCP REST, UCP MCP and A2A.

Source: https://storeware.ai/docs/agents/after-the-sale

The jobs a shop's own [MCP server](https://storeware.ai/docs/agents/mcp) does for an assistant also work through UCP. Each is declared on the shop's profile at `https://<shop>/.well-known/ucp` under a Storeware name, with its schema at `https://api.storeware.ai/schemas/ucp/<date>/<name>.json`. Every call takes the agent key and your profile, as in [Calling it](https://storeware.ai/docs/agents/ucp-acp#calling-it). Over MCP the arguments sit beside `meta`, and over A2A they are a DataPart naming the tool, as for [Ask](https://storeware.ai/docs/agents/ask).

## A shopper's orders and returns

`ai.storeware.shopping.post_purchase`. These need a key a shopper linked (see [Identity linking](https://storeware.ai/docs/agents/ucp-acp#identity-linking)). A key nobody linked is refused with `identity_required`. Writes also need the shop to let linked assistants act, a setting the merchant controls. When it is off, the answer is `capability_unsupported` and the shopper can do it on the shop's website.

| Job                                | REST, under `/api/ucp/v1`                | MCP tool                        |
| ---------------------------------- | ---------------------------------------- | ------------------------------- |
| List my orders                     | `GET /orders?limit=`                     | `list_my_orders`                |
| Stop an unpaid, undispatched order | `POST /orders/{id}/cancel`               | `cancel_order`                  |
| Ask the shop to stop one           | `POST /orders/{id}/cancellation-request` | `request_cancellation`          |
| What can go back                   | `GET /orders/{id}/returnable-lines`      | `returnable_lines`              |
| Open a return                      | `POST /returns`                          | `request_return`                |
| One return, or all of them         | `GET /returns/{id}`, `GET /returns`      | `get_return`, `list_my_returns` |
| Withdraw a return                  | `POST /returns/{id}/cancel`              | `cancel_return`                 |
| Buy an order again                 | `POST /orders/{id}/reorder`              | `reorder`                       |
| A link to a file the order bought  | `POST /orders/{id}/downloads`            | `get_download_link`             |

A return names `order_id` and `line_items`, each with a `line_item_id` from the returnable lines, a `quantity` and a `reason` code. An agent may also open a return on an order it placed itself, without a linked shopper. Buying again answers with a new checkout, and anything that could not be repeated is a warning in its `messages`.

## Files a shopper bought

When an order bought downloads, Get Order (`GET /orders/{id}` or `get_order`) lists them under `ai.storeware.shopping.post_purchase.downloads`. This happens only when your profile declares `ai.storeware.shopping.post_purchase` and a shopper linked the key, and only for that shopper's own order. Each entry has `line_item_id`, `asset_id`, the file's `name`, `downloads_remaining` (null is unlimited) and `available`. When a file cannot be had, `unavailable` says why (`unpaid`, `canceled`, `refunded` or `exhausted`) and `reason` says it in a sentence. Reading the order spends nothing.

To fetch one, send `line_item_id` and `asset_id` to `POST /orders/{id}/downloads`, or call `get_download_link` with the order's `id`. The answer has the file's `name`, a `url`, its `expires_at` and the `downloads_remaining` after it. The link is the one the shop's own receipt page hands out. It works for a few minutes and anybody holding it can open the file, so pass it to the shopper straight away and do not store it. Each new link counts as one download. Asking again while the last link still works answers with an equivalent link, marked `reissued`, and counts nothing.

An unpaid, cancelled or fully refunded order is refused with `download_unavailable`, and a spent allowance with `download_limit_reached`. A file that is not on the order, and an order that is not the shopper's, are both `not_found`. Over the shop's own [MCP server](https://storeware.ai/docs/agents/mcp), `track_order` lists the same files and `get_download_link` takes `order_id`, `line_item_id` and `asset_id`.

## Errands

`ai.storeware.shopping.watch`, open to any agent key. Leave an errand against a variant with `POST /watches` or `watch_for_it`: when it is back in stock, or at or under a price, the shop records it. Read it with `GET /watches/{id}` or `get_watch`. The first read after the condition is met carries `handoff`, a single-use token for one checkout at that price, and no later read does. List with `GET /watches` and withdraw with `POST /watches/{id}/cancel`.

## Gift cards and discount codes

`ai.storeware.shopping.gift_card`. Redeem a code into a basket with `POST /checkout-sessions/{id}/gift-cards` or `POST /carts/{id}/gift-cards`, sending `{ "code": "..." }`, or the tools `apply_gift_card` and `apply_cart_gift_card`. The answer is the checkout or cart, with what the card was worth under `ai.storeware.shopping.gift_card`. A code is spent once, so send an idempotency key when you retry.

A cart takes `discounts.codes` the way a checkout does, and shows what they took off under `discounts`.

## Subscriptions

`ai.storeware.shopping.selling_plan`. When your profile declares it, a product lists its plans under that key. To subscribe, send `selling_plan_id` on a checkout or cart line. A plan the item is not sold on is refused with `selling_plan_not_offered` and the line is left out, never bought once in its place. Send `null` to buy a line once. Leave the field out and a line keeps the plan it had.

A subscription is kept on an account, so a basket holding one is placed only for a shopper who signed in or linked the shop. Managing a subscription after it starts (pausing, skipping, cancelling) is for the shopper on the shop's own website. No key can do it.

## Terms

`request_terms` and `accept_terms` on UCP MCP do what `POST /checkout-sessions/{id}/terms` and `POST /checkout-sessions/{id}/terms/{offer_id}/accept` do over REST: ask the shop to take something off a basket, with a reason and the total you want, then take the signed offer.
