Coinbase API Portal: Complete Guide for Crypto Traders
Learn how to use the Coinbase API portal, set up authentication, and build trading tools with real Python code examples for algorithmic crypto trading.
Learn how to use the Coinbase API portal, set up authentication, and build trading tools with real Python code examples for algorithmic crypto trading.
If you've spent any time trading crypto seriously, you've probably hit the ceiling of what manual trading can do. The Coinbase API portal is the gateway that lets you move beyond clicking buttons — automating orders, pulling live market data, and building systems that work while you sleep. Whether you're coming from Binance's API ecosystem or exploring Coinbase for the first time, this guide gives you everything you need to go from zero to making authenticated API calls.
The Coinbase API is a programmatic interface that lets developers and traders interact with Coinbase's trading infrastructure directly — without a browser. Through it, you can fetch real-time prices, place market and limit orders, check account balances, retrieve transaction history, and automate virtually any action you'd normally do manually in the Coinbase interface. Coinbase actually offers two separate API products worth knowing: the Coinbase Exchange API (aimed at pro traders and institutions, previously Coinbase Pro) and the Coinbase Advanced Trade API, which is the current standard for retail algorithmic trading. The two have overlapping functionality but different endpoints and authentication flows.
Coinbase deprecated Coinbase Pro in late 2023. If you're starting fresh, use the Advanced Trade API — it's the current supported product and the one the Coinbase API portal is built around.
Yes — the Coinbase API is free to access. There's no subscription fee or cost to generate API keys or make API calls. What you pay for is trading: standard maker/taker fees apply to any orders you place through the API, identical to fees on the web platform. This is consistent across major exchanges: Binance, Bybit, OKX, and Coinbase all offer free API access with fees tied to actual trades, not API usage itself.
Rate limits are the practical constraint. The Advanced Trade API enforces limits by endpoint — typically 10 requests per second for private endpoints and higher for public market data endpoints. If you're building a high-frequency system, you'll want to implement request queuing and exponential backoff from day one, not as an afterthought. Platforms like Bybit and OKX have more generous rate limits for some endpoint categories, so it's worth benchmarking your use case before committing to a single exchange.
| Endpoint Type | Rate Limit | Notes |
|---|---|---|
| Market Data (public) | 10 req/sec | No auth required |
| Account & Orders (private) | 10 req/sec | Requires API key |
| WebSocket feeds | No request limit | Subscription-based, persistent connection |
| Bulk order operations | Varies | Check docs per endpoint |
The Coinbase API portal lives at developer.coinbase.com. This is your central hub for documentation, API key management, and credential setup. To get started with authenticated access — required for anything touching your account — you need to complete the Coinbase API login flow through your existing Coinbase account.
Coinbase now supports CDP (Coinbase Developer Platform) API keys with Ed25519 signing in addition to legacy HMAC keys. New projects should use CDP keys — they're more secure and better supported going forward.
Coinbase's Advanced Trade API uses HMAC-SHA256 request signing for legacy keys. Every private request must include a signature built from your secret key, the timestamp, request method, path, and body. Here's a clean implementation:
import hmac
import hashlib
import time
import requests
import os
API_KEY = os.environ.get('COINBASE_API_KEY')
API_SECRET = os.environ.get('COINBASE_API_SECRET')
BASE_URL = 'https://api.coinbase.com'
def get_signature(timestamp, method, path, body=''):
message = f'{timestamp}{method.upper()}{path}{body}'
signature = hmac.new(
API_SECRET.encode('utf-8'),
message.encode('utf-8'),
digestmod=hashlib.sha256
).hexdigest()
return signature
def make_request(method, path, body=None):
timestamp = str(int(time.time()))
body_str = body if body else ''
signature = get_signature(timestamp, method, path, body_str)
headers = {
'CB-ACCESS-KEY': API_KEY,
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'Content-Type': 'application/json'
}
url = f'{BASE_URL}{path}'
response = requests.request(method, url, headers=headers, data=body_str)
response.raise_for_status()
return response.json()
# Test: fetch account balances
try:
accounts = make_request('GET', '/api/v3/brokerage/accounts')
for account in accounts.get('accounts', []):
if float(account['available_balance']['value']) > 0:
print(f"{account['currency']}: {account['available_balance']['value']}")
except requests.exceptions.HTTPError as e:
print(f'API error: {e.response.status_code} - {e.response.text}')
Once authentication is working, fetching market data and placing orders follows the same pattern. Here's how to get the current BTC-USD price and place a market buy order:
import json
import uuid
# Get best bid/ask for BTC-USD
def get_best_bid_ask(product_id='BTC-USD'):
path = f'/api/v3/brokerage/best_bid_ask?product_ids={product_id}'
data = make_request('GET', path)
pricebook = data['pricebooks'][0]
print(f"BTC Best Ask: ${pricebook['asks'][0]['price']}")
print(f"BTC Best Bid: ${pricebook['bids'][0]['price']}")
return pricebook
# Place a market order
def place_market_order(product_id, side, quote_size):
"""
side: 'BUY' or 'SELL'
quote_size: USD amount to spend (for BUY) or base size (for SELL)
"""
order_payload = json.dumps({
'client_order_id': str(uuid.uuid4()),
'product_id': product_id,
'side': side,
'order_configuration': {
'market_market_ioc': {
'quote_size': str(quote_size) # spend this many USD
}
}
})
try:
result = make_request('POST', '/api/v3/brokerage/orders', body=order_payload)
order = result['success_response']
print(f"Order placed: {order['order_id']}")
print(f"Status: {order['status']}")
return order
except requests.exceptions.HTTPError as e:
error_data = e.response.json()
print(f"Order failed: {error_data.get('error', 'Unknown error')}")
print(f"Preview failure: {error_data.get('preview_failure_reason', '')}")
return None
# Example usage
get_best_bid_ask('BTC-USD')
# place_market_order('BTC-USD', 'BUY', 10) # Buy $10 of BTC
REST calls are great for one-off queries, but live trading systems need streaming data. Coinbase's WebSocket feed delivers real-time price ticks, order book updates, and trade executions without polling. The WebSocket endpoint requires the same authentication headers as REST calls, embedded in the subscription message.
import websocket
import json
import time
import hmac
import hashlib
WS_URL = 'wss://advanced-trade-ws.coinbase.com'
def get_ws_signature(timestamp, channel, product_ids):
product_str = ','.join(product_ids)
message = f'{timestamp}{channel}{product_str}'
return hmac.new(
API_SECRET.encode('utf-8'),
message.encode('utf-8'),
digestmod=hashlib.sha256
).hexdigest()
def on_message(ws, message):
data = json.loads(message)
if data.get('channel') == 'ticker':
for event in data.get('events', []):
for ticker in event.get('tickers', []):
print(f"{ticker['product_id']}: ${ticker['price']} "
f"(24h: {ticker['price_percent_chg_24h']}%)")
def on_error(ws, error):
print(f'WebSocket error: {error}')
def on_open(ws):
timestamp = str(int(time.time()))
product_ids = ['BTC-USD', 'ETH-USD']
channel = 'ticker'
subscribe_msg = {
'type': 'subscribe',
'product_ids': product_ids,
'channel': channel,
'api_key': API_KEY,
'timestamp': timestamp,
'signature': get_ws_signature(timestamp, channel, product_ids)
}
ws.send(json.dumps(subscribe_msg))
print('Subscribed to ticker feed')
ws = websocket.WebSocketApp(
WS_URL,
on_open=on_open,
on_message=on_message,
on_error=on_error
)
ws.run_forever()
This WebSocket approach is what powers real-time trading signal platforms like VoiceOfChain, which aggregates live price feeds and on-chain data to surface actionable signals the moment market conditions shift. Combining WebSocket price streams with signal data gives your bot both the trigger and the context to act intelligently — not just mechanically.
The Coinbase API portal gives you everything you need to graduate from manual trading into systematic execution. The authentication setup takes under an hour, the endpoints are well-documented, and the Python examples above give you a working foundation to build on. Whether you're pulling signals from a platform like VoiceOfChain to trigger Coinbase orders automatically, or building a portfolio tracker that aggregates positions across Coinbase, Binance, and OKX — the API is the foundation that makes it possible. Start with read-only keys while you develop, add trade permissions only when your logic is battle-tested, and always store credentials in environment variables. The difference between a trader who codes and a coder who trades is just experience — and you just got some.