Short answer: For trading code, the Coinbase sandbox means two different test environments, so test in the one that matches the API you will call in production. The Coinbase Exchange sandbox (api-public.sandbox.exchange.coinbase.com) has its own login, API keys, unlimited fake funds and order books; the Advanced Trade sandbox (api-sandbox.coinbase.com) needs no key and returns fixed, mocked responses. Neither shows production prices or fills: on 5 November 2026 the Exchange sandbox had 9 online markets against 516 in production.
This guide rests on Coinbase's developer documentation, read on 5 November 2026, and on requests sent that day from Python 3.11 with no account and no real keys; private endpoints were called only to record their errors.
It is a technical guide, not a recommendation of any platform or strategy. Automated trading can lose money, and which products you may use depends on your jurisdiction and Coinbase's terms. For readers in Turkey: Article 99/A of Capital Markets Law No. 6362 treats activity by foreign crypto-asset platforms directed at Turkish residents as unauthorized.
Which Coinbase sandbox do you need?
Choose by the production API: Exchange code belongs in the Exchange sandbox, Advanced Trade code can only be checked against canned responses, and payment checkouts have their own sandbox.
| Item | Exchange sandbox | Advanced Trade sandbox | Checkouts sandbox |
|---|---|---|---|
| Login and keys | Separate sandbox login and keys | None | Coinbase Business account; same CDP keys as production |
| Funds | Unlimited fake funds; no transfers | Fixed mocked balances | Testnet USDC on Base Sepolia |
| Market data | Own books, 9 online markets | None (404) | Not applicable |
| Can prove | Signing, order flow, FIX sessions (documented; not tested here) | Response parsing, documented error branches | Checkout and webhook flow |
| Cannot prove | Production prices, depth, slippage | Signing, order logic, state | Real settlement |
Coinbase's Advanced Trade FAQ describes the Exchange APIs as serving institutional clients, with API keys requiring a Coinbase Exchange account. A fourth environment, the CDP Sandbox (sandbox.cdp.coinbase.com), simulates custodial accounts and transfers with no blockchain activity. Other venues' testnets are compared in the paper trading API guide.
Coinbase Exchange sandbox: login, account and API keys
You sign up separately at the sandbox web interface, create keys there and add fake money from the Portfolios tab; Coinbase's sandbox page says logins and API keys are separate from production.
- Login. The page links to
public.sandbox.exchange.coinbase.com, which on 5 November 2026 answered HTTP 301 topublic-sandbox.exchange.coinbase.com(200). Documented steps: create an account or sign in, open API from the profile menu, click New API Key. The page does not say who may sign up or whether verification is needed; no account was created for this guide. - Funds. The Deposit button on the Portfolios tab adds unlimited fake funds; Withdraw removes them. The five transfer endpoints, for deposits and withdrawals, are unavailable.
- Keys. Signing uses four
CB-ACCESS-*headers and HMAC-SHA256, as in the sample below; the timestamp must be within 30 seconds of the API's time, and a lost passphrase cannot be recovered. Permissions are View, Trade, Transfer and Manage; see creating exchange API keys and API key security for trading bots.
| Interface | Sandbox | MiCA sandbox |
|---|---|---|
| REST | api-public.sandbox.exchange.coinbase.com | api-us.dma.sandbox.prime.coinbase.com |
| WebSocket feed | ws-feed-public.sandbox.exchange.coinbase.com | ws-us.dma.sandbox.prime.coinbase.com |
| FIX order entry | fix-ord.sandbox.exchange.coinbase.com:6121 | fix-us.dma.sandbox.prime.coinbase.com:7110 |
The page also lists direct WebSocket, FIX market data and drop copy hosts for each column, plus a certificate FIX clients must validate. That certificate expired on 25 April 2023; on 5 November 2026 both order-entry hosts above presented newer, valid ones in a TLS handshake, so do not pin it. The page says MiCA clients must use the second column but does not define who counts as one; this guide makes no claim about EU law. Both REST hosts answered without a key, with the same product list and BTC-USD trade IDs from one sequence.
Coinbase sandbox API: what answered on 5 November 2026
Public Exchange sandbox endpoints answered without a key, private ones returned errors worth knowing in advance, and the market was far thinner than production.
| Request | Result |
|---|---|
/time, /products/BTC-USD, ticker, level 1 book, candles, WebSocket ticker | Answered normally |
/products | 13 products, 9 online; production 845, 516 online |
| BTC-USD spread, ten samples, 20:00 to 20:02 | 10.28 to 427.49 USD; production 0.01 to 2.88 USD |
| BTC-USD 24-hour volume, 20:01 | 376.46 BTC; production 13,434.06 BTC |
GET /accounts, unsigned | 401 Unauthorized. |
| Same, signed with a random unregistered key | 500 Internal Server Error. in every try |
| Same, timestamp 40 seconds old | 401 request timestamp expired |
A wrong key produced a server error rather than a 401, so a client that retries every 5xx would retry a credentials problem forever; this is observed, not documented, behavior and may change.
Hypothetical example. A server's clock runs 40 seconds slow. Public calls keep working, but every signed request falls outside the 30-second window and returns 401 request timestamp expired. A startup check against /time with a margin you choose, such as 25 seconds (illustrative, not a Coinbase figure), catches it before any order.
Coinbase Advanced Trade sandbox: fixed data, retired endpoints included
The Advanced Trade sandbox returns the same canned data to every caller, so it checks how your code reads responses, not how it trades.
- Static.
GET /accountsreturned four accounts (100 USDC, 1 ETH, 100 USD, 0.5 BTC), identical on a second call, andPOST /orderswith an empty body returned success. - Coverage. The page's note says Accounts and Orders only, but its 18-row table adds Portfolios and Perpetuals. All 10 GET rows returned 200, the
/intxones with the INTX portfolio's UUID; of the 8 POST rows, 6 returned 200 and the two/intxones 400 withoutportfolio_uuidand, with it, 404This endpoint has been retired./productsreturned 404. - Retired endpoints still mocked. Coinbase's Advanced Trade REST page says INTX perpetuals trading ended on 1 October 2026 and the
/intx/*endpoints are retired. The sandbox still served a mocked ETH-PERP-INTX position on 5 November 2026, so a test that passes there says nothing about production. Perpetual futures are leveraged derivatives and carry a high risk of fast, large losses.
JWT signing, orders, rate limits and the X-Sandbox error triggers are covered in the Coinbase Advanced Trade API Python guide.
Coinbase Pro sandbox: what the old hosts do now
Coinbase Pro is gone, but its old sandbox API host still answered, and its old web address now leads to a production page.
Coinbase's Advanced Trade FAQ says Pro was disabled and all customers migrated as of 1 December 2023, and that Pro API keys cannot trade on Advanced Trade. On 5 November 2026:
api-public.sandbox.pro.coinbase.comanswered with the same 13 products and ticker as the Exchange sandbox. No page read for this guide lists it, so it can vanish without notice.public.sandbox.pro.coinbase.com, the old sandbox web address, answered 301 towww.coinbase.com/advanced-trade/spot/BTC-USD, a production trading page. An old tutorial can put you on the live site.
The sample below refuses any host not on its sandbox list and follows no redirects.
Coinbase Commerce sandbox and the Checkouts API sandbox
No Commerce sandbox page was found in Coinbase's developer documentation on 5 November 2026, only a guide for migrating from Commerce to the Checkouts API, which has one.
- Migration. The base URL moves from
api.commerce.coinbase.comtobusiness.coinbase.com/api/v1/checkouts, authentication moves to CDP API keys with JWT Bearer tokens, and the guide suggests testing in the sandbox. It gives no end date for Commerce; its FAQ says existing Commerce webhooks keep working for the Charge API. - Checkouts sandbox. Insert
/sandboxinto the path (business.coinbase.com/sandbox/api/v1/checkouts) and use the same CDP keys. Payments arrive in USDC on Base Sepolia; the portal faucet gives 1 testnet USDC per claim, 10 claims per 24 hours. Webhook subscriptions need the labelsandboxset totrueor they receive only production events. Refunds are capped at 2.00 USD and data is purged after 30 days. - Observed. Both Checkouts URLs returned 401 without a key. On 5 November 2026 the Commerce FAQ page returned HTTP 502 at every attempt and
api.commerce.coinbase.com/chargesHTTP 530: one day's observation, not evidence that Commerce has closed.
Testing a Coinbase Exchange sandbox client in Python
Guard the host, check the clock, sign as documented and keep error classes apart; this ran against the public Exchange sandbox on 5 November 2026 (Python 3.11.3, requests 2.31.0).
import base64, hashlib, hmac, json, os, time
from decimal import Decimal, InvalidOperation
import requests
SANDBOX = "https://api-public.sandbox.exchange.coinbase.com"
SANDBOX_HOSTS = {SANDBOX, "https://api-us.dma.sandbox.prime.coinbase.com"}
class AuthError(Exception): pass
class ApiError(Exception): pass
class SandboxClient:
def __init__(self, base=SANDBOX, key="", secret="", passphrase=""):
if base not in SANDBOX_HOSTS: # never reach production by mistake
raise ValueError(f"not a sandbox host: {base}")
self.base, self.key, self.passphrase = base, key, passphrase
self.secret = base64.b64decode(secret) if secret else b""
def call(self, method, path, body=None, signed=False, ts=None):
data, headers = (json.dumps(body) if body else ""), {"Content-Type": "application/json"}
if signed:
if not (self.key and self.secret and self.passphrase):
raise AuthError("key, secret or passphrase missing")
ts = ts or str(time.time())
mac = hmac.new(self.secret, (ts + method + path + data).encode(), hashlib.sha256)
headers |= {"CB-ACCESS-KEY": self.key, "CB-ACCESS-TIMESTAMP": ts,
"CB-ACCESS-SIGN": base64.b64encode(mac.digest()).decode(),
"CB-ACCESS-PASSPHRASE": self.passphrase}
r = requests.request(method, self.base + path, data=data or None, headers=headers,
timeout=10, allow_redirects=False) # signed headers stay on this host
try:
payload = r.json()
except ValueError:
payload = None
msg = payload.get("message", "") if isinstance(payload, dict) else ""
if r.status_code == 401:
raise AuthError(msg)
if r.status_code >= 300 or payload is None: # signed 500: check the key, do not retry
raise ApiError(f"HTTP {r.status_code} {msg}")
return payload
def to_increment(value, step):
try:
d, step = Decimal(value), Decimal(step)
ok = d.is_finite() and d > 0 and d == d.quantize(step)
except (InvalidOperation, TypeError):
ok = False
if not ok:
raise ValueError(value)
return format(d.quantize(step), "f")
c = SandboxClient()
print("clock skew under 30 s:", abs(c.call("GET", "/time")["epoch"] - time.time()) < 30)
btc = c.call("GET", "/products/BTC-USD")
print(btc["id"], btc["status"], to_increment("1E+2", btc["quote_increment"]))
for bad in ["1e400", "1e-400", "nan", "0.000000001"]:
try:
to_increment(bad, btc["base_increment"])
except ValueError:
print("rejected", bad)
fake = dict(key=os.urandom(16).hex(), secret=base64.b64encode(os.urandom(64)).decode(),
passphrase="synthetic")
for client, ts in [(SandboxClient(), None), (SandboxClient(**fake), None),
(SandboxClient(**fake), str(time.time() - 3600))]:
try:
client.call("GET", "/accounts", signed=True, ts=ts)
except (AuthError, ApiError) as err:
print(type(err).__name__, err)
try:
SandboxClient(base="https://api.exchange.coinbase.com")
except ValueError as err:
print(err)
Output:
clock skew under 30 s: True
BTC-USD online 100.00
rejected 1e400
rejected 1e-400
rejected nan
rejected 0.000000001
AuthError key, secret or passphrase missing
ApiError HTTP 500 Internal Server Error.
AuthError request timestamp expired
not a sandbox host: https://api.exchange.coinbase.com
The signed calls use a random key made at run time, so they test only error paths: missing credentials stop before any network call, the unregistered key gets the 500, the stale timestamp the 401. A successful signed request needs a sandbox account's key and was not run. Amounts stay strings: 1e400, 1e-400, nan and sizes finer than base_increment are refused rather than sent as infinity or zero, and 1E+2 goes out as 100.00. Redirects are refused because requests 2.31.0, by default, passed all four CB-ACCESS-* headers to the host a 301 named in a local mock test.
Retry design is in crypto exchange API integration and limits for live tests in trading bot risk management. For integration work in general, see exchange API integration; naming Coinbase here does not mean Fincode integrates it or has built on it.
Frequently asked questions
Is there a Coinbase sandbox login?
Yes, for the Exchange sandbox: a separate sign-up at public.sandbox.exchange.coinbase.com, which redirected to public-sandbox.exchange.coinbase.com on 5 November 2026. The Advanced Trade sandbox has no login.
Can I use my Coinbase API key in the sandbox?
Not in the Exchange sandbox, whose keys are separate from production. The Advanced Trade sandbox needs no key, and the Checkouts sandbox takes the same CDP keys as production.
Does the Coinbase sandbox use real market prices?
No. In ten samples on 5 November 2026, 20:00 to 20:02 UTC, the Exchange sandbox BTC-USD spread ranged from 10.28 to 427.49 USD, against 0.01 to 2.88 USD in production; Advanced Trade sandbox values are fixed.
Does the Coinbase Pro sandbox still work?
Coinbase says Pro was disabled and all customers migrated as of 1 December 2023. Its old sandbox API host still answered on 5 November 2026, but no current page read for this guide lists it, so use the documented Exchange sandbox hosts.
Sources
- Coinbase Developer Docs: Exchange Sandbox (hosts, fake funds, unsupported transfers, MiCA hosts) (opens in a new tab)
- Coinbase Developer Docs: Exchange Systems and Operations (production and MiCA production hosts) (opens in a new tab)
- Coinbase Developer Docs: Exchange REST API authentication (CB-ACCESS headers, 30-second window) (opens in a new tab)
- Coinbase Developer Docs: Advanced Trade API Sandbox (opens in a new tab)
- Coinbase Developer Docs: Advanced Trade REST endpoints (INTX retired, 1 October 2026) (opens in a new tab)
- Coinbase Developer Docs: Advanced Trade API FAQ (Coinbase Pro migration, Exchange clients) (opens in a new tab)
- Coinbase Developer Docs: Checkouts API Sandbox Environment (opens in a new tab)
- Coinbase Developer Docs: Migrate from Commerce, overview (opens in a new tab)
- Coinbase Developer Docs: Migrate from Commerce, FAQ and resources (opens in a new tab)
- Coinbase Developer Docs: CDP Sandbox overview (opens in a new tab)
- Coinbase Exchange sandbox: live public products endpoint (opens in a new tab)
- Capital Markets Law No. 6362, Article 99/A (Turkish, consolidated text) (opens in a new tab)
This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the editorial policy.