> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cdp.coinbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Simple Retail Watchlist

The Simple Retail Watchlist API reads and changes the authenticated customer's
ordered primary watchlist in the Coinbase app. This is not an Advanced Trade
product watchlist API.

The API supports reading, adding, removing, and reordering items. Mutations
operate on one item at a time. It does not support bulk changes, secondary
watchlists, or selecting a watchlist by ID.

## Endpoints

| Operation | HTTP request | OAuth scope |
| :- | :- | :- |
| Read the primary watchlist | `GET /v2/watchlist/items` | `wallet:watchlist:read` |
| Add an item | `POST /v2/watchlist/items` | `wallet:watchlist:update` |
| Remove an item | `POST /v2/watchlist/items/remove` | `wallet:watchlist:update` |
| Reorder an item | `POST /v2/watchlist/items/reorder` | `wallet:watchlist:update` |

The base URL is `https://api.coinbase.com`. Send an OAuth access token as a
Bearer token. `POST` requests use `Content-Type: application/json` and a JSON
request body.

Request and response field names use Protobuf JSON lower camel case. Responses
are direct Protobuf JSON messages and do not use a `data` wrapper.

## Authorization

The two scopes are independent:

* `wallet:watchlist:read` authorizes only `GET /v2/watchlist/items`.
* `wallet:watchlist:update` authorizes add, remove, and reorder mutations.

Neither scope implies the other. A client with only the update scope cannot
read the resulting watchlist. After a mutation, request and receive the read
scope separately before calling `GET /v2/watchlist/items`.

Access is limited to the authenticated customer's primary watchlist. Requests
do not accept a customer, account, portfolio, tenant, or watchlist ID.
Primary-watchlist selection and every storage operation are scoped to the
authenticated customer.

## Item references

An `item` object must contain exactly one identifier field. Native identifiers
are converted to canonical form when added. For assets, reads return the stored
token CBRN when one is present and return `assetUuid` only for UUID-only rows.
Reads return typed CBRNs for every other item type.

| Simple Retail item type | Accepted identifier fields | Canonical field returned by `GET` | `expiresAt` on add |
| :- | :- | :- | :- |
| Asset | `assetUuid` or `tokenCbrn` | `tokenCbrn`, or `assetUuid` for UUID-only rows | Not allowed |
| Prediction position | `predictionEventId` or `predictionCbrn` | `predictionCbrn` | Required |
| Prediction series | `predictionSeriesId` or `predictionSeriesCbrn` | `predictionSeriesCbrn` | Not allowed |
| Future | `futureProductId` or `futureCbrn` | `futureCbrn` | Required |
| Perpetual | `perpetualProductId`, `deribitPerpetualInstrumentId`, or `perpetualCbrn` | `perpetualCbrn` | Optional |
| Equity | `equityProductId` or `equityCbrn` | `equityCbrn` | Not allowed |
| IPO | `ipoProductId` or `ipoCbrn` | `ipoCbrn` | Not allowed |
| Equity option | `equityOptionProductId` or `equityOptionCbrn` | `equityOptionCbrn` | Optional |
| Crypto option | `deribitCryptoOptionInstrumentId` or `cryptoOptionCbrn` | `cryptoOptionCbrn` | Required |
| Token sale | `tokenSaleCbrn` | `tokenSaleCbrn` | Required |

`expiresAt`, when present, is a Protobuf JSON timestamp in RFC 3339 format and
must be in the future. It is part of an add request, not the item reference.

### Canonical identifier forms

* `assetUuid` is a UUID. `tokenCbrn` must be a token CBRN such as
  `v1:token:base:mainnet:0xBaseTokenAddress:`.
* Prediction position and prediction series CBRNs use
  `v1:derivative:kalshi:event:<native-id>:`. The identifier field preserves
  whether the item is a position or a series.
* Future CBRNs use `v1:derivative:cde:future:<product-id>:`.
* CDE perpetual CBRNs use `v1:derivative:cde:perp:<product-id>:`. Deribit
  perpetual CBRNs use `v1:derivative:deribit:perp:<instrument-id>:`.
* Equity and IPO CBRNs use `v1:equity:::<product-id>:`. The identifier field
  preserves whether the item is an equity or an IPO.
* Equity option CBRNs use `v1:equity_option:::<product-id>:`.
* Crypto option CBRNs use
  `v1:derivative:deribit:option:<instrument-id>:`.
* `tokenSaleCbrn` uses the token CBRN format. The identifier field distinguishes
  a token sale from an asset.

Deribit perpetual and crypto option instrument IDs must contain only decimal
digits. A numeric `perpetualProductId` is still a CDE product ID. Use
`deribitPerpetualInstrumentId` to identify a numeric Deribit instrument.

For non-asset items, the API validates the CBRN resource type and derivative
provider where applicable. Obtain native IDs and typed CBRNs from the relevant
Coinbase product API, which determines resource existence and customer
eligibility.

## Read the watchlist

Returns all representable items in the primary watchlist's persisted ascending
order. The endpoint has no request body, filters, or pagination. If the
customer does not have a primary watchlist, it returns an empty Protobuf JSON
message (`{}`) without creating one. The default Protobuf JSON encoding
omits the `items` field when it is empty.

Malformed or unsupported stored items are omitted so that they do not make
valid items unreadable. The relative order of all returned items is preserved.

### Request

```shell theme={null}
curl https://api.coinbase.com/v2/watchlist/items \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
```

### Response

Each object has exactly one field. This example covers every supported Simple
Retail item type and uses the canonical form returned by the generated model.

```json theme={null}
{
  "items": [
    {
      "tokenCbrn": "v1:token:base:mainnet:0xBaseTokenAddress:"
    },
    {
      "predictionCbrn": "v1:derivative:kalshi:event:market-123:"
    },
    {
      "predictionSeriesCbrn": "v1:derivative:kalshi:event:KXHIGHNY:"
    },
    {
      "futureCbrn": "v1:derivative:cde:future:BIT-28NOV25-CDE:"
    },
    {
      "perpetualCbrn": "v1:derivative:deribit:perp:12345:"
    },
    {
      "equityCbrn": "v1:equity:::AAPL:"
    },
    {
      "ipoCbrn": "v1:equity:::ACME:"
    },
    {
      "equityOptionCbrn": "v1:equity_option:::test-option-123:"
    },
    {
      "cryptoOptionCbrn": "v1:derivative:deribit:option:125191:"
    },
    {
      "tokenSaleCbrn": "v1:token:ethereum:mainnet:0x1234567890abcdef:"
    }
  ]
}
```

## Add an item

Adds one item to the end of the authenticated customer's primary watchlist. If
the customer does not have a primary watchlist, the API creates the
canonical primary watchlist before adding the item.

The API resolves `assetUuid` and `tokenCbrn` inputs authoritatively. A valid
token CBRN is stored and returned with its network identity. When no token CBRN
is stored for an asset row, `GET` returns its `assetUuid`. An authoritative
missing result is treated as invalid input; a
resolver outage is treated as an internal dependency failure.

Native non-asset IDs are converted to their typed CBRNs before storage.
Adds use the app's existing duplicate-matching behavior. For non-asset items,
the same CBRN can match an existing entry even when the requested item type
differs. Do not assume that the same Kalshi event CBRN can be added as both a
prediction position and a prediction series in one watchlist.

Asset duplicate handling also depends on existing stored references and
uniqueness constraints. A network-specific token CBRN does not guarantee a
separate entry for an asset that is already watched.

When an existing entry is matched, adding it succeeds without adding or moving
a row and without replacing its expiration. Read the watchlist to confirm the
persisted identifiers and membership; do not infer a new row from the empty
mutation response.

### Request

This example adds an equity by its native product ID:

```shell theme={null}
curl -X POST https://api.coinbase.com/v2/watchlist/items \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"item":{"equityProductId":"AAPL"}}'
```

An expiring item includes `expiresAt` alongside `item`:

```json theme={null}
{
  "item": {
    "futureProductId": "BIT-28NOV30-CDE"
  },
  "expiresAt": "2030-11-28T23:00:00Z"
}
```

### Response

```json theme={null}
{}
```

The empty object acknowledges the idempotent mutation. It does not return the
added item or the watchlist. To observe the result, call
`GET /v2/watchlist/items` with a token that separately has
`wallet:watchlist:read`.

## Remove an item

Removes one item by its stored typed identity. Removing an absent item, removing
from a missing primary watchlist, and a concurrent delete race all succeed as
no-ops. Removing an item does not change the relative order of the remaining
items.

Removal does not repeat asset resolution or product eligibility checks. This
allows a customer to remove a stale, expired, or delisted item. Prefer the
canonical identifier returned by `GET /v2/watchlist/items`. For an asset, use
the returned `tokenCbrn` when present, or `assetUuid` when the row has no stored
token CBRN.

### Request

```shell theme={null}
curl -X POST https://api.coinbase.com/v2/watchlist/items/remove \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"item":{"tokenCbrn":"v1:token:base:mainnet:0xBaseTokenAddress:"}}'
```

### Response

```json theme={null}
{}
```

The empty object acknowledges the idempotent mutation. It does not return the
removed item or the watchlist. Reading the result requires a separate
`wallet:watchlist:read` grant.

## Reorder an item

Move an existing item immediately before or after another item in your watchlist.
Use `item` plus exactly one of `beforeItem` or `afterItem`. Each reference uses
the same identifier format as add/remove; prefer identifiers returned by `GET`.
To move an item to the front, place it before the current first item; to move
it to the end, place it after the current last item. If it is already at the
requested edge, skip the request. Never use the item itself as its anchor.

```shell theme={null}
curl -X POST https://api.coinbase.com/v2/watchlist/items/reorder \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"item":{"equityProductId":"AAPL"},"beforeItem":{"equityProductId":"MSFT"}}'
```

This example assumes both items are already in the watchlist. Success returns
`{}` and requires `wallet:watchlist:update`; it does not grant permission to read
the resulting list. Reordering changes no membership, identifiers, or expiration.

* Moving an item that is already in the requested position succeeds without a write.
* Missing items or anchors are rejected; a missing watchlist is not created.
* Both positions, neither position, or moving an item relative to itself are invalid.
* Ambiguous references are rejected before any write. If an asset UUID matches
  multiple network-specific entries, use the token CBRN returned by `GET`.
* Other items retain their relative order. No catalog lookup is needed, so stored
  stale or delisted items can still be reordered.
* Concurrent edits follow the app's existing read-modify-write ordering behavior.
  This is not an atomic full-list replacement or a version-checked write. Reread
  after completion or an uncertain outcome before deciding whether to retry.

## Error contract

The API groups malformed input, unsupported input, and
authoritatively missing assets as invalid input. It separately distinguishes
dependency failures, authentication failures, and missing method-specific
scopes. It does not define an endpoint-specific HTTP status mapping or JSON
error envelope.
