'Unauthorized' return message in CLI following Advanced Trade API guidelines

Hello, I am setting up my dev environment for the new Advanced Trade API. I am transferring from CB Pro and a lot has changed! I am following instructions for python on the Advanced Trading API docs

However, I return ‘Unauthorized’ when running the curl command:
curl -H "Authorization: Bearer $JWT" 'https://api.coinbase.com/api/v3/brokerage/accounts

I have done the following troubleshooting before posting:

  1. I am also aware there is a 48 hour security feature where api keys are not live. I created api key on December 24. But it seems like my key is still not working / registering.
  2. When I enter: echo $JWT in my terminal I see the alphanumerical string of the jwt token set to the environment variable, JWT.

Thanks in advanced…

Here is my code:

import jwt
from cryptography.hazmat.primitives import serialization
import time
key_name = "organizations/MY_ORG_ID/apiKeys/MY_KEY_ID"
key_secret = "-----BEGIN EC PRIVATE KEY-----\nMY_KEY_HERE\n-----END EC PRIVATE KEY-----\n"


request_method = "GET"
request_host = "api.coinbase.com"
request_path = "/api/v3/brokerage/accounts"
service_name = "retail_rest_api_proxy"

def build_jwt(service, uri):
    private_key_bytes = key_secret.encode('utf-8')
    private_key = serialization.load_pem_private_key(private_key_bytes, password=None)
    jwt_payload = {
        'sub': key_name,
        'iss': "coinbase-cloud",
        'nbf': int(time.time()),
        'exp': int(time.time()) + 60,
        'aud': [service],
        'uri': uri,
    }
    jwt_token = jwt.encode(
        jwt_payload,
        private_key,
        algorithm='ES256',
        headers={'kid': key_name, 'nonce': str(int(time.time()))},
    )
    return jwt_token
def main():
    uri = f"{request_method} {request_host}{request_path}"
    jwt_token = build_jwt(service_name, uri)
    print(f"export JWT={jwt_token}")
if __name__ == "__main__":
    main()

And is that same JWT that was generated before you tried to use curl?

That example does not automatically export variable! You need to do that manually. So you first call that python script, then run generated command to set/export variable and only then run curl command.

Or even better update that script to make GET request:

import jwt
from cryptography.hazmat.primitives import serialization
import time
import http.client

key_name = ""
key_secret = ""

request_method = "GET"
request_host = "api.coinbase.com"
request_path = "/api/v3/brokerage/accounts"
service_name = "retail_rest_api_proxy"

def build_jwt(service, uri):
    private_key_bytes = key_secret.encode('utf-8')
    private_key = serialization.load_pem_private_key(private_key_bytes, password=None)
    jwt_payload = {
        'sub': key_name,
        'iss': "coinbase-cloud",
        'nbf': int(time.time()),
        'exp': int(time.time()) + 60,
        'aud': [service],
        'uri': uri,
    }
    jwt_token = jwt.encode(
        jwt_payload,
        private_key,
        algorithm='ES256',
        headers={'kid': key_name, 'nonce': str(int(time.time()))},
    )
    return jwt_token

def main():
    uri = f"{request_method} {request_host}{request_path}"
    jwt_token = build_jwt(service_name, uri)
    #print(f"export JWT={jwt_token}")
    
    conn = http.client.HTTPSConnection("api.coinbase.com")
    conn.request("GET", request_path, '', {
      'Authorization': 'Bearer ' + jwt_token,
    })
    
    res = conn.getresponse()
    data = res.read()
    
    print(data.decode("utf-8"))

if __name__ == "__main__":
    main()