Advanced Trade REST API Authentication
This page explains how to authenticate each endpoint with an API key.
The Advanced Trade REST API comprises all v3
endpoints. It does not duplicate the Sign In With Coinbase v2
endpoints for core Coinbase functions (some of which need authentication as well).
To send requests to the Advanced Trade API, you must sign and authenticate each v3
endpoint. You can do so with with an API Key or with OAuth2.
For help with OAuth2, refer to the Sign In documentation on OAuth2.
Signing Requests
You can use the same API Key authentication scheme for both the Advanced Trade API (v3) and Sign In API (v2) although you need different scopes.
All Advanced Trade REST API requests must contain the following headers:
CB-ACCESS-KEY
: The API key as a string (that you create on coinbase.com)CB-ACCESS-TIMESTAMP
: A timestamp for your requestCB-ACCESS-SIGN
: The encoded signature
For example:
--header "CB-ACCESS-KEY: Sd55555555555tP3"
--header "CB-ACCESS-SIGN: 35f238402bb2400aeb0a048dab64d6cd82d99590da255bd9afe1c1f37fd1686d"
--header "CB-ACCESS-TIMESTAMP: 1667500462"
To create a signed request, you must:
- Generate an API key at
coinbase.com/settings/api
and copy the API key string for theCB-ACCESS-KEY
and the API secret to create the signature. - Set a timestamp for the
CB-ACCESS-TIMESTAMP
header. - Create an encoded signature as the
CB-ACCESS-SIGN
header (with the API secret). - Apply the headers to the request. You are ready to send.
Step 1: Generate API Key
To start, create an API key at coinbase.com/settings/api. API keys do not expire.
Copy the API key string and API secret. Apply the API key to the CB-ACCESS-KEY
header. Keep the API secret to create the signature below.
An Advanced Trade API key is scoped to an account, not a profile (or portfolio). See API Scopes for a workaround.
Step 2: Set Timestamp
The CB-ACCESS-TIMESTAMP
header MUST be a UNIX timestamp and it must be the same timestamp used to create the request signature, +/-30 seconds. Decimal values are not allowed. Make sure to use an integer.
Step 3: Create Signature
The CB-ACCESS-SIGN
header is generated by creating a sha256 HMAC object using the API secret key on the string timestamp + method + requestPath + body
.
Create a signature string by concatenating the values of these query parameters:
timestamp + method + requestPath + body
.Concatenate the values of the following parameters with the
+
operator: these query parameters: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.
See SigGen Code Samples below.
Request Path
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 Sign In requestPath
does include query parameters.
API | requestPath | Valid Example |
---|---|---|
Advanced Trade (v3) | API endpoint | /api/v3/brokerage/products/BTC-USD/ticker |
Sign In (v2) | API endpoint + query params | /v2/exchange-rates?currency=USD |
/api/v3/brokerage/products/BTC-USD/ticker
https://coinbase.com/api/v3/brokerage/products/BTC-USD/ticker?limit=3
// Ruby code sample of a GET Request Signature Flow
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
SigGen Code Samples
The following examples demonstrate how to generate a signature in Python, Ruby, and JavaScript:
Python
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)
Ruby
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)
JavaScript
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)
See Also: