Skip to content
BaseHub by Will Binns Updated

Tokenized Stocks API

Coinbase runs a small HTTP API that hands back reference data for its tokenized stocks on Base. It is public and read-only, and it needs no API key. One request gets you what would otherwise take several onchain reads per token: the contract address, supply, current multiplier, pause state, and the latest Chainlink reference value.

https://api.coinbase.com/v1/tokenized-stocks
MethodPathReturns
GET/Every tokenized-stock record the API currently exposes.
GET/chainsThe tokenized-stocks protocol contracts, per supported chain.
GET/total-supply/{contract_address}One token’s total supply, normalized by its decimals.
GET/metadata/{ticker}A contractURI-style metadata document for one token.
GET/images/{symbol}A 302 redirect to the token’s icon.
GET/prospectus/{ticker}A 302 redirect to the token’s approved prospectus PDF.
GET/prospectusesTickers that currently have a cached prospectus, with ISINs where known.
GET/corporate-actions/{id}One announced or applied corporate action.

The full schema lives upstream in openapi/tokenized-equities.json.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks

The response is a tokens array and, when more records exist, a next_page_token. Each entry is a v1TokenizedEquityToken:

FieldTypeMeaning
contract_addressstringThe ERC-20 (B20) token contract on Base.
symbolstringTicker symbol of the token.
namestringName of the underlying equity.
decimalsintegerToken decimals.
icon_urlstringIcon for the underlying equity.
total_supplydoubleSupply in token units, already divided by decimals.
isinstringISIN of the underlying equity.
multiplierdoubleCurrent token-to-share scaling factor. 1.0 means no adjustment.
paused_featuresinteger[]Feature flags currently paused on the token contract.
nav_pricedoubleLatest Chainlink NAV/reference value, adjusted for the feed’s decimals.
nav_price_updated_atdate-timeWhen nav_price last changed onchain (the feed’s updatedAt).
descriptionstringLong-form description of the tokenized stock.
first_mint_datedate-timeUTC block time of the token’s first positive mint. This is not the deploy time, and later mints or burns never move it.

Not every field appears on every record. The API drops scalar fields that hold their default value, empty arrays, and timestamps that were never set. first_mint_date is also missing when a token has never been minted or when its first mint has not been resolved yet. On 2026-10-17 the full list had 174 records. 116 of them had no total_supply key (zero supply), and only 58 carried first_mint_date. Write your parser so a missing key means “default or unknown”, and never read a missing nav_price as a usable price.

The list is paged, so one call can miss records. If a response has next_page_token, send it back as the page_token query parameter to get the next page. Stop when a response has no next_page_token. Leave every other query parameter the same from one page to the next. Records come back sorted by contract address.

page_size sets the page length. Omitting it, or sending 0, gives 100. Anything above 500 is quietly cut to 500. A negative or malformed page_size, or a malformed page_token, fails with HTTP 400.

Terminal window
curl "https://api.coinbase.com/v1/tokenized-stocks?page_token=<next_page_token>"

This is not a corner case. On 2026-10-14 a call with no parameters returned 100 records and a next_page_token. Walking every page returned 145 records (174 by 2026-10-17). Code that reads only the first response misses about a third of the tokens and gets no error. Upstream added pagination to its docs on 2026-10-13.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks/chains

Returns a chains array of v1ChainContractAddresses entries, each with chain_id, chain, policy_registry_address, token_supply_manager_address, and token_factory_address. On 2026-09-25 it listed one chain, Base (8453):

FieldValue
policy_registry_address0x8453000000000000000000000000000000000002
token_supply_manager_address0xD1Ca4dAcdf3231011D175351f1f02D15C7c5664C
token_factory_address0x4bA3E29E254F25E94E61C4c9d67b37027331534D

The policy registry is the B20 PolicyRegistry precompile, not a separate deployment. Treat the live response as authoritative over this table.

The example below uses the AAPLc contract. For any other token, take its address from the list endpoint above.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks/total-supply/0xb200000000000000000000C2e324d24d7eEcd1fb

The body is a bare JSON number, such as 7459.11648989 for AAPLc on 2026-10-17. There is no wrapping object and no total_supply key, so a parser that looks for one gets nothing. The value is already divided by the token’s decimals; do not divide it again.

A badly formed address gets HTTP 400 with service code 3. A well-formed address that is not a supported tokenized stock gets HTTP 404 with service code 5.

Pass the token symbol with its suffix, for example TSLAc. Case does not matter.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks/metadata/TSLAc

The document has contract_address, name, symbol, description, image, and prospectus_url. Both URLs point back at this API and redirect to whatever asset is current, so they stay stable. A prospectus_url is always present, but that does not mean a PDF is cached right now. Check the cached prospectus list below before you rely on it.

Pass the symbol with its suffix. Case does not matter, and the .png ending is optional.

Terminal window
curl -L https://api.coinbase.com/v1/tokenized-stocks/images/TSLAc.png --output TSLAc.png

A hit returns HTTP 302 with the real image location in the Location header; -L tells curl to follow it. There is no JSON body. An unknown symbol gets 404, and missing token data gets 503, both as plain text.

Pass the ticker with its suffix. Case does not matter, the .pdf ending is optional, and dotted share classes such as BRK.Bc work.

Terminal window
curl -L https://api.coinbase.com/v1/tokenized-stocks/prospectus/TSLAc.pdf --output TSLAc.pdf

A hit returns HTTP 302 to the approved prospectus PDF; on 2026-10-17 the TSLAc redirect pointed at a file on adgm.com. A malformed ticker gets 400, and a ticker with no prospectus available gets 404. Both errors are plain text, not JSON.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks/prospectuses

The body holds a prospectuses array in alphabetical order of the upper-cased ticker. Each item has a ticker and, if known, the underlying equity’s isin. The tickers come back fully upper-cased (AAPLC, not AAPLc), which is fine because the prospectus endpoint ignores case. No PDF links are included; feed the ticker to the prospectus endpoint instead.

The cache fills in the background. Until its first good refresh it can be empty, and then the prospectuses key can be absent altogether. This list tells you which prospectuses are on hand. It is not a list of tradable tokens. On 2026-10-17 it held 177 entries.

Terminal window
curl https://api.coinbase.com/v1/tokenized-stocks/corporate-actions/e82812a6-0b24-41c4-8ed1-322d1b466d33

That ID is a GOOGLc cash dividend. Get the ID from the UUID at the end of the uri in the token’s onchain Announcement event. Do not use the event’s id argument; it can be a plain number or carry a suffix like :pre or -1. The GOOGLc example shows why: its announcement history has one entry with ID 2097 and a second whose ID is the UUID. Announcements that have no addressable URI cannot be fetched here.

The body is the action itself, not wrapped in a corporate_action key. It carries the token, a description, the status, the first announcement time, and the onchain announcements in time order. Announcement block_number values are decimal strings.

  • CORPORATE_ACTION_STATUS_ANNOUNCED: published, but the token’s multiplier has not changed yet.
  • CORPORATE_ACTION_STATUS_APPLIED: the multiplier change is in effect. Only in this state are applied_at, multiplier_before, and multiplier_after filled in.

The multiplier values are already converted out of their 18-decimal fixed-point form. A malformed UUID gets 400. An unknown action, or one on a test or non-live token, gets 404. Stale or unavailable action data gets 503.

The JSON endpoints report failures as an object with code and message. code is a service error code, not the HTTP status:

{"code": 3, "message": "page_token is invalid"}
HTTP statuscodeWhen
4003Bad input: malformed page token, negative page size, invalid contract address, or malformed corporate action UUID.
4045The token, ticker, or corporate action is unsupported or does not exist.
50314Data the request needs is temporarily unavailable.

The icon and prospectus endpoints are the exception. They answer success with a 302 and send their errors as plain text.

The field names look familiar from the onchain interface, but several of them carry different units here. Most integration mistakes with this API come from mixing the two.

  • total_supply counts tokens, not shares. To get the share count, multiply it by multiplier.
  • multiplier is already scaled down. Onchain the multiplier is WAD-scaled (18 decimals). The API divides that out, so a token with no adjustment reports 1, not 1e18. Do not apply the WAD division a second time.
  • multiplier moves. Dividends and splits change it, so read the current value each time you convert units to shares. Never cache it as a constant.
  • nav_price is a reference value, not a quote. It is the total-return figure from the token’s Chainlink feed. It is not a bid, an ask, or a fill price.
  • nav_price goes stale without warning. Chainlink publishes a new round only on a price deviation or a heartbeat, and the feeds stop outside market hours. So nav_price_updated_at can trail the clock by minutes or by many hours. Apply the same staleness bound you would apply to updatedAt from latestRoundData().

Two response details surfaced when this page was checked against the live API on 2026-09-25:

  • paused_features is left out entirely when nothing is paused, rather than sent as an empty array. Treat a missing key as “no pauses”. Upstream now documents this as the general rule for all default-valued fields.
  • The list held exactly the ten launched tokens (AAPLc through TSLAc). COINc, CRCLc, and INTCc, which are registered onchain but have zero supply, were not in it. That is no longer true: by 2026-10-17 the list included zero-supply tokens such as RKTc, with total_supply simply omitted.