Advanced Trade API Legacy Key Authentication
Legacy API key authentication is supported but optional for both Advanced Trade and Sign in with Coinbase APIs. Coinbase recommends that you generate keys on the Coinbase Developer Platform (CDP).
Legacy API keys are for individuals or applications for individual use. They can be used with Advanced REST APIs & WebSocket channels (except new features).
Creating Legacy Keys
Generate an API key on Coinbase.com and copy the API key string and API secret to create a signature.
- Login and navigate to https://www.coinbase.com/settings/api.
- Select New API Key and enter you 2FA code.
- Configure the following key details:
- Accounts
- Permissions
- Notifications
- Allowlist IPs
- Securely store the values of your new API key and API secret. They will not be shown again.
Signing Requests
All Advanced Trade REST API requests with legacy API keys must contain the following headers:
Header | Description |
---|---|
CB-ACCESS-KEY | API key as a string (that you create on coinbase.com) |
CB-ACCESS-SIGN | Encoded signature using API secret |
CB-ACCESS-TIMESTAMP | Timestamp for your request |
Advanced Trade does not require a PASSPHRASE
as did Coinbase Pro.
Creating a Signature
-
Create a signature string by concatenating the values of these query parameters with the
+
operator:timestamp + method + requestPath + body
.timestamp
is the same as theCB-ACCESS-TIMESTAMP
header (+/-30 seconds)method
should be UPPER CASErequestPath
is the full path (minus the base URL and query parameters), for example:/api/v3/brokerage/orders/historical/fills
/api/v3/brokerage/products/BTC-USD/ticker
body
is the request body string -- it is omitted if there is no request body (typically forGET
requests)
-
Create a sha256 HMAC object with your API secret on the signature string.
-
Get the hexadecimal string representation of the sha256 HMAC object and pass that in as the
CB-ACCESS-SIGN
header.
A signature must be in lowercase letters or the program throws a 401 error.
Signature Code Samples
The following examples demonstrate how to generate a signature in Python, Ruby, and JavaScript:
- Python
- Ruby
- JavaScript
import json, hmac, hashlib, time, base64
#timestamp = str(int(time.time()))
#request.method = GET or POST
#request.path_url.split('?')[0] = /api/v3/brokerage/orders/historical/batch
message = timestamp + request.method + request.path_url.split('?')[0] + str(request.body or '')
signature = hmac.new(secretKey.encode('utf-8'), message.encode('utf-8'), digestmod=hashlib.sha256).digest()
print(signature.hex(), ts)
timestamp = Time.now.to_i
payload = "#{timestamp}#{method}#{request_path}#{body}";
# create a sha256 hmac with the secret
signature = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
const CryptoJS = require('crypto-js');
function sign(str, secret) {
const hash = CryptoJS.HmacSHA256(str, secret);
return hash.toString();
}
const timestamp = Math.floor(Date.now() / 1000).toString();
const str = timestamp + req.Method + req.Path + req.Body
const sig = sign(str, apiSecret)
The Advanced Trade requestPath
should only include the path of the API endpoint in the string for hashing. It should not include the base URL (protocol and domain) nor any query parameters. By contrast, the SIWC requestPath
does include query parameters.
API | requestPath | Valid Example |
---|---|---|
Advanced (v3) | API endpoint | /api/v3/brokerage/products/BTC-USD/ticker |
SIWC (v2) | API endpoint + query params | /v2/exchange-rates?currency=USD |
Making Requests
All private API requests must include CB-ACCESS-* headers:
- Set a timestamp for the
CB-ACCESS-TIMESTAMP
header. - Create an encoded signature as the
CB-ACCESS-SIGN
header (with the API secret). - Set your legacy API key for the
CB-ACCESS-KEY
header. - Apply the headers to the request. You are ready to send.
Example Request
curl https://api.coinbase.com/v3/brokerage/accounts \
--header "CB-ACCESS-KEY: <your api key>" \
--header "CB-ACCESS-SIGN: <the user generated message signature>" \
--header "CB-ACCESS-TIMESTAMP: <a timestamp for your request>"
All requests should have content type application/json
and the body must be valid JSON.
// Ruby code sample of a GET Request to product ticker
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://coinbase.com/api/v3/brokerage/products/BTC-USD/ticker?limit=3")
request_path= "/api/v3/brokerage/products/BTC-USD/ticker"
body = ""
method = "GET"
timestamp = Time.now.to_i
payload = "#{timestamp}#{method}#{request_path}#{body}"
# create a sha256 hmac with the secret
signature = OpenSSL::HMAC.hexdigest('sha256', $SECRET_KEY, payload)
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["accept"] = 'application/json'
request["CB-ACCESS-KEY"] = $ACCESS_KEY
request["CB-ACCESS-SIGN"] = signature
request["CB-ACCESS-TIMESTAMP"] = timestamp
response = http.request(request)
puts response.read_body