GuidesAPI Reference
DocumentationLog In

Authenticating Messages

๐Ÿšง

Coinbase Advanced Trade API is in Beta. We welcome your feedback in the forums!

To send requests to the Advanced Trade API, you must sign and authenticate each endpoint with an API key. This page explains how.

๐Ÿ‘

You can use the same API Key authentication scheme for both the Advanced Trade API (v3) and Sign In API (v2) although you will need different scopes.

Signing Requests

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 request
  • CB-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:

  1. Generate an API key at coinbase.com/settings/api and copy the API key string for the CB-ACCESS-KEY and the API secret to create the signature.
  2. Set a timestamp for the CB-ACCESS-TIMESTAMP header.
  3. Create an encoded signature as the CB-ACCESS-SIGN header (with the API secret).
  4. 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.

  1. 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 the CB-ACCESS-TIMESTAMP header (+/-30 seconds)
    • method should be UPPER CASE
    • requestPath 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 for GET requests)
  2. Create a sha256 HMAC object with your API secret on the signature string.

  3. 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.

APIrequestPathValid 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

๐Ÿ‘

Advanced Trade requestPath Examples

ValidValid Valid: /api/v3/brokerage/products/BTC-USD/ticker
InvalidInvalid Invalid: 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: