Coinbase API Documentation: Complete Guide for Traders
Master the Coinbase API documentation to automate trading, fetch market data, and build powerful crypto bots with Python examples and real endpoints.
Master the Coinbase API documentation to automate trading, fetch market data, and build powerful crypto bots with Python examples and real endpoints.
If you've spent any time trying to automate your crypto trading, you've probably hit the wall of confusing documentation, broken examples, and endpoints that don't behave the way you expect. Coinbase's API ecosystem is actually one of the more mature in the industry — but it's fragmented across multiple products, and knowing which documentation to use for your use case saves hours of frustration.
This guide cuts through that confusion. Whether you're building a personal trading bot, pulling historical candle data, or integrating institutional-grade execution via Coinbase Prime, you'll know exactly where to look and how to authenticate correctly.
Coinbase doesn't have one API — it has several, each targeting a different audience. This is the first thing the coinbase api documentation makes clear, and it's worth understanding before writing a single line of code.
Most traders want the Advanced Trade API. If you're coming from Coinbase Pro, that API is deprecated — migrate to Advanced Trade. The coinbase api reference for Advanced Trade is the authoritative source.
Coinbase moved away from simple API key + secret authentication toward JWT (JSON Web Token) signing for the Advanced Trade API. This is more secure but trips up a lot of developers used to how Binance or Bybit handle auth — where you just HMAC-sign a query string with your secret.
Here's how to generate a signed JWT request using the official coinbase api documentation python approach:
import jwt
import time
import secrets
import requests
from cryptography.hazmat.primitives import serialization
# Your API credentials from Coinbase Developer Portal
API_KEY_NAME = "organizations/{org_id}/apiKeys/{key_id}" # format from CDP portal
PRIVATE_KEY_PEM = """
-----BEGIN EC PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END EC PRIVATE KEY-----
"""
def build_jwt(method: str, path: str) -> str:
"""Build a signed JWT for Coinbase Advanced Trade API."""
private_key = serialization.load_pem_private_key(
PRIVATE_KEY_PEM.encode(), password=None
)
uri = f"{method} api.coinbase.com{path}"
payload = {
"sub": API_KEY_NAME,
"iss": "cdp",
"nbf": int(time.time()),
"exp": int(time.time()) + 120,
"uri": uri,
"nonce": secrets.token_hex(10),
}
token = jwt.encode(
payload,
private_key,
algorithm="ES256",
headers={"kid": API_KEY_NAME, "nonce": secrets.token_hex(10)},
)
return token
# Example: fetch account balances
path = "/api/v3/brokerage/accounts"
token = build_jwt("GET", path)
response = requests.get(
f"https://api.coinbase.com{path}",
headers={"Authorization": f"Bearer {token}"}
)
if response.status_code == 200:
accounts = response.json().get("accounts", [])
for acc in accounts:
if float(acc["available_balance"]["value"]) > 0:
print(f"{acc['currency']}: {acc['available_balance']['value']}")
else:
print(f"Error {response.status_code}: {response.json()}")
Compare this to how Bybit or OKX handle authentication — both use HMAC-SHA256 with timestamp + nonce in headers, which is simpler to implement manually. Coinbase's JWT approach is more modern and arguably more secure, but requires the cryptography library and careful key management.
One of the most common use cases is pulling OHLCV candle data for backtesting or live signal generation. The coinbase rest api documentation covers the product candles endpoint under the Market Data section.
import requests
import time
from datetime import datetime, timedelta
def get_candles(product_id: str, granularity: str, days_back: int = 1):
"""
Fetch OHLCV candles from Coinbase Advanced Trade API.
granularity options: ONE_MINUTE, FIVE_MINUTE, FIFTEEN_MINUTE,
THIRTY_MINUTE, ONE_HOUR, TWO_HOUR, SIX_HOUR, ONE_DAY
"""
end_time = int(time.time())
start_time = end_time - (days_back * 86400)
url = f"https://api.coinbase.com/api/v3/brokerage/products/{product_id}/candles"
params = {
"start": str(start_time),
"end": str(end_time),
"granularity": granularity,
"limit": 300, # max per request
}
response = requests.get(url, params=params)
if response.status_code != 200:
raise Exception(f"API error: {response.status_code} — {response.json()}")
candles = response.json().get("candles", [])
# Parse and return as list of dicts
result = []
for c in candles:
result.append({
"time": datetime.utcfromtimestamp(int(c["start"])),
"open": float(c["open"]),
"high": float(c["high"]),
"low": float(c["low"]),
"close": float(c["close"]),
"volume": float(c["volume"]),
})
return sorted(result, key=lambda x: x["time"])
# Fetch hourly BTC-USD candles for last 7 days
candles = get_candles("BTC-USD", "ONE_HOUR", days_back=7)
print(f"Fetched {len(candles)} candles")
print(f"Latest close: ${candles[-1]['close']:,.2f}")
The candles endpoint is public and doesn't require authentication — no JWT needed for market data. This is useful for read-only bots and signal scanners that don't need to place orders.
The coinbase developer documentation for order placement is one area where reading carefully pays off. Coinbase uses a unified order creation endpoint with a configuration object that differs by order type — market, limit, stop-limit, etc.
import uuid
def place_market_order(
product_id: str,
side: str, # "BUY" or "SELL"
quote_size: str = None, # for BUY: amount in USD
base_size: str = None, # for SELL: amount in BTC/ETH etc.
) -> dict:
"""Place a market order on Coinbase Advanced Trade."""
path = "/api/v3/brokerage/orders"
token = build_jwt("POST", path) # from auth example above
# Build order config based on side
if side == "BUY" and quote_size:
order_config = {
"market_market_ioc": {
"quote_size": quote_size # e.g. "100.00" = spend $100
}
}
elif side == "SELL" and base_size:
order_config = {
"market_market_ioc": {
"base_size": base_size # e.g. "0.001" = sell 0.001 BTC
}
}
else:
raise ValueError("Provide quote_size for BUY or base_size for SELL")
payload = {
"client_order_id": str(uuid.uuid4()), # unique per order
"product_id": product_id,
"side": side,
"order_configuration": order_config,
}
response = requests.post(
f"https://api.coinbase.com{path}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
json=payload,
)
result = response.json()
if not result.get("success"):
error = result.get("error_response", {})
raise Exception(f"Order failed: {error.get('message', 'Unknown error')}")
order = result["success_response"]
print(f"Order placed: {order['order_id']} — {side} {product_id}")
return order
# Example usage (paper trade before using real funds!)
# place_market_order("ETH-USD", "BUY", quote_size="50.00")
Notice the client_order_id field — this is your idempotency key. If your network request times out and you're not sure if the order landed, you can resubmit with the same client_order_id and Coinbase won't double-fill you. Platforms like Binance have similar mechanisms, but the implementation differs — always check exchange-specific docs.
Coinbase publishes an official Python SDK as part of the coinbase sdk documentation. For most use cases, using the SDK is faster to get running than building JWT auth from scratch.
For production bots handling real capital, raw HTTP calls give you more control over retry logic, timeouts, and error handling. For scripts, backtests, and prototypes, the SDK is the right call. The coinbase api doc examples in the official GitHub repo are a good starting point — search for coinbase/coinbase-advanced-py on GitHub.
If you're combining Coinbase data with signals from other sources — say, order book pressure from OKX or funding rate anomalies from Bitget — you'll end up building your own abstraction layer anyway. Platforms like VoiceOfChain aggregate these cross-exchange signals in real time, which can feed directly into your execution logic on Coinbase without you having to poll multiple APIs yourself.
The Coinbase API ecosystem rewards traders who take the time to read the actual coinbase api reference rather than copying random Stack Overflow snippets. JWT auth is a stumbling block for newcomers, but once you have the signing logic working, the rest of the API is well-structured and reliable.
Start with the public candle endpoint — no auth required, and it lets you validate your data pipeline before touching orders. Then wire up authentication, test against paper trading or very small sizes, and only scale up when you trust your error handling. Combine Coinbase execution with real-time cross-exchange signal feeds from platforms like VoiceOfChain, and you have a serious edge over traders clicking buttons manually on the web UI.