Coinbase Pro API Authentication

Authenticate Coinbase Pro API

  • Managing API keys is not currently supported on the Coinbase Pro mobile app. Select the API link from the menu .
  • Under Profile Information, select the API Settings tab, then select + New API Key.Select your profile and appropriate permissions, create a passphrase, and then enter in your 2-Factor Authentication code.

Rachel Gomez

I got this python code to create a working signature:

key = base64.b64decode(secret)
msg = message.encode(‘utf-8’)
ash = hmac.digest(key, msg, hashlib.sha256)
sig = base64.b64encode(ash).decode(‘utf-8’)

But when I tried it with javascript and AHK, creating the same signature, {“message”:“invalid signature”} gets returned.

Any ideas why that might be. Is there some difference in the signature string?

I haven’t found that the ‘Accept’ line is required for authentication.
And the secret is used as the key.
Maybe check your signature against one made by python.

Here’s a CryptoJS snippet that works:

var key = CryptoJS.enc.Base64.parse(secret);
var hash = CryptoJS.HmacSHA256(message, key);
var signature = hash.toString(CryptoJS.enc.Base64);

Answering my own question above, in case it’s of any help to others:

I found out that an AHK script I had made was rejected as having an invalid signature, even though the correct signature was generated. It was rejected because I didn’t send the variable body in the send command, along with the headers having the signature, passphrase, etc.

Hey all, new here and got pretty excited about using the api.
I’m using node js and was able to try @larry.kubin test code.
Everything works fine on the GET request and I can see the filled orders.
I’d like to also be able to POST requests which I’m having a bit of difficulty trying to figure out.
Also, it is a bit confusing that I can’t find any working samples for the Coinbase Pro api.
I tried using larry’s code by switching the GET to Post and creating a body for the transaction, but I’m getting a

statusCode: 401
{"message":"invalid signature"}

I’d like to be able to post buy orders at a specific set price as well as market price.
Any help and pointers in the right direction are greatly appreciated.

thank you!

This and other threads have info on making a valid signature.

Ok, tried it with cryptojs as well and same thing.
This is what I have so far:

const config = require('dotenv').config();
var CryptoJS = require("crypto-js");
const https = require('https');

var cb_access_timestamp = / 1000;
var cb_access_passphrase = process.env.cb_access_passphrase;
var cb_api_key = process.env.cb_api_key;
var cb_secret = process.env.cb_secret;

var path = '/orders';
var body = JSON.stringify({
    price: '45415.51',
    size: '0.0001',
    side: 'buy',
    product_id: 'BTC-USD'
var method = 'POST';

var message = cb_access_timestamp + method + path + body;

var key = CryptoJS.enc.Base64.parse(cb_secret);
var hash = CryptoJS.HmacSHA256(message, key);
var sign = hash.toString(CryptoJS.enc.Base64);

const options = {
  hostname: '',
  port: 443,
  path: path,
  method: method,
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': 0,
    'User-Agent': 'MyTradingBot',
    'CB-ACCESS-KEY': cb_api_key,
    'CB-ACCESS-PASSPHRASE': cb_access_passphrase,
    'CB-ACCESS-SIGN': sign,
    'CB-ACCESS-TIMESTAMP': cb_access_timestamp

const req = https.request(options, res => {
  console.log(`statusCode: ${res.statusCode}`)

  res.on('data', d => {

req.on('error', error => {


Still getting:

statusCode: 401
{"message":"invalid signature"}

I can see you’re missing type:limit. Maybe you need strings like this:

'product_id': 'BTC-USD',
'type': 'limit',
'side': 'buy',
'price': '25000',
'size': '0.00001'

added that… no difference :frowning:

Maybe s.o. who knows JS can help. What does your message string look like?

In case it is helpful, I have had success with the Python code below (or as a Github Gist) which is a slight tweak to @SubStandard’s code above, mainly adding the passphrase (I’m not sure if the other changes were important but this works for me).

import time
import hmac
import hashlib
import requests
import base64

class CoinbaseAuth(requests.auth.AuthBase):
	def __init__(self, api_key, secret_key, api_passphrase):
		self.api_key = api_key
		self.api_passphrase = api_passphrase
		self.secret_key = base64.b64decode(secret_key)
	def __call__(self, request):
		timestamp = str(time.time())
		message = timestamp + request.method + request.path_url + (request.body or '')
		signature = base64.b64encode(, message.encode(), hashlib.sha256).digest())
			'CB-ACCESS-SIGN': signature,
			'CB-ACCESS-TIMESTAMP': timestamp,
			'CB-ACCESS-KEY': self.api_key,
			'CB-ACCESS-PASSPHRASE': self.api_passphrase
		return request


API_KEY = 'xxx'
API_SECRET = 'xxx'


r = requests.get(COINBASE_API + '/oracle', auth=auth)
1 Like

@cleggink I think I had a couple things incorrect. Most notably, my prehashString included path instead of body. I got it working and wrote a synopsis: Coinbase Cloud with GoLang

@arood I was able to get it working. I made a couple errors building the “Signing Message”. I wrote an article: Coinbase Cloud with GoLang. Hopefully, this will help others avoid some of the mistakes I made. (Github link → jhennin/coinbase-cloud-go)

1 Like

Please see Proper REST signatures for the entire signature walkthru, this is covered there.

Thanks for the link @cleggink, must of missed it when I jumped back into working on this.

1 Like

I don’t mean to hijack this thread but I don’t see an option to create a new one so here goes…
With Python:
I’ve successfully gotten authenticated and can access my /accounts info…
I am trying to now access /conversions to convert a coin to another linked coin.
I am receiving a response from the API of {"message":"Internal server error"}

I am fairly sure my post body is correct. I’d be happy to elaborate and post some of my code, if needed.

Is this error on my end or is the API doing something wonky right now?

@wolfpunkjs there should be a response code that comes with that error message to help you clarify the exact reason for the error.

@cleggink Yes, it’s showing:

{"message":"Internal server error"}

Hello @wolfpunkjs, thank you for joining the conversation. Since this is already a different topic, we’ve created a new thread specifically for your inquiry. Please refer to this thread: Internal Server Error when calling conversions endpoint.

We can continue our collaboration in the new thread. Thanks.

You’re a life saver!! this authentication was killing me, thanks for the help!