Skip to main content
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

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. 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

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.

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:
An expiring item includes expiresAt alongside item:

Response

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

Response

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.
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.