Invalid API key - response when trying to get account info

New here, have read similar posts on the forum but still unclear how to proceed. I get an An Invalid API Key response when I try the following:

Endpoint

private string LIVE = "https://api.coinbase.com";

I created an API Key in my Coinbase account however it did not ask for a passphrase, so I guess I should remove sending that header?

And this invokes the endpoint for getting account info. Just starting with /account REST call to get things working… However, I’ve seen responses in the forum saying I should use the above endpoint base URL but the docs here (API Docs - https://docs.cloud.coinbase.com/exchange/reference), say I should use

https://api.exchange.coinbase.com/accounts

When I change the URL to include the “exchange” hostname in the path, I get a “Not found” response… Also, where in the world is my account ID listed in the CB website / portal? I had copied it months ago into my test code but now I’m getting back to doing more testing / learning with CB API and wanted to make sure I had my account ID correct. However, I looked everywhere and could not find it.

Not sure how to proceed. I’m not trying to use new(er) version of Pro / Advanced API, just the basic Exchange API. Here’s the connection code in C#

string response = "";
            try
            {
                string method = System.Net.Http.HttpMethod.Get.ToString();
                string timestamp = TimeHelper.GetCurrentUnixTimestampSeconds();
                string sign = ControllerSignature.Generate(
                                timestamp, 
                                method, 
                                path, 
                                body, 
                                ModelConfig.Secret);  

                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    request.Headers.Add(HeaderNames.AccessKey,ModelConfig.Key);
                    request.Headers.Add(HeaderNames.AccessSign,sign);
                    request.Headers.Add(HeaderNames.AccessTimestamp,timestamp);
                    request.Headers.Add(HeaderNames.AccessPassphrase,ModelConfig.Passphrase);
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var uaInfo = new ProductInfoHeaderValue(USER_AGENT_BOT_NAME, USER_AGENT_VERSION);
                    request.Headers.UserAgent.Add(uaInfo);  
                    var responseTask  = await client.SendAsync(request);                    
                    response = await responseTask.Content.ReadAsStringAsync();
                    //onsole.Write("Response is: " + response);  
                    return response;                                  
                }
            }

If you are individual then forget about Pro / Exchange APIs. You have to use Advanced Trade and/or Sign in with Coinbase APIs:

3 Likes

Ok… let me try this.

Where do I find my account ID?

List Accounts endpoint?:
https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getaccounts

2 Likes

Ok, I updated the code and read the docs for Advanced Trade (I guess this was formerly Pro?) and now I get

“Unauthorized”

as a response… I created the API key, secret and called:

https://api.coinbase.com/api/v3/brokerage/accounts

No, Advanced Trade is new thing…

You have not provided anything that could help understand what is your problem. Anyway here are few guesses:

  • I think there was some waiting time (24 or even 48 hours) for new keys;
  • Make sure API key has correct permissions;
  • Make sure you are not base64 decoding secret and/or signature in case you are coming from Pro;
  • Make sure you are generating signature correctly.
2 Likes

Thanks, here I’m creating the signature. I have IP restriction on my Key but I’m connecting from the correct IP. That’s only other thing I know to list here to figure out the issues.

I’m not decoding base64 on my access secret but am encoding the signature result before I attach to the REST header.

      public static string Generate(string timestamp, string method, string requestPath, string body, string appSecret)
      {
         return Sign(appSecret, timestamp + method + requestPath + body);
      }

      internal static string Sign(string key, string data)
      {
         var hmacKey = Encoding.UTF8.GetBytes(key);
         var dataBytes = Encoding.UTF8.GetBytes(data);

         using (var hmac = new HMACSHA256(hmacKey))
         {
            var sig = hmac.ComputeHash(dataBytes);
            return Convert.ToBase64String(sig);
         }
      }

From the original code above I posted, here’s how I use the API Key and the signature:

                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    request.Headers.Add(HeaderNames.AccessKey,ModelConfig.Key);
                    request.Headers.Add(HeaderNames.AccessSign,sign);
                    request.Headers.Add(HeaderNames.AccessTimestamp,timestamp);

Anyway, I’m still getting “Unauthorized” in my responses.

Why?

Get the hexadecimal string representation of the sha256 HMAC object and pass that in as the CB-ACCESS-SIGN header.

2 Likes

Hmm, I tried with converting to hex string and still get “Unauthorized”, here’s the update signature function:

      internal static string Sign(string key, string data)
      {
         var hmacKey = Encoding.UTF8.GetBytes(key);
         var dataBytes = Encoding.UTF8.GetBytes(data);

         using (var hmac = new HMACSHA256(hmacKey))
         {
            var sig = hmac.ComputeHash(dataBytes);
            return Convert.ToHexString(sig);
         }
      }

Provide more complete code? That shows also how timestamp is generated, what method and path is used.

2 Likes

Here’s the code and debug values:

private static async Task<string> TryProcessAsync(string url, string body, string path)
        {
            string response = "";
            try
            {
                string method = System.Net.Http.HttpMethod.Get.ToString();
                string timestamp = TimeHelper.GetCurrentUnixTimestampSeconds();
                string sign = ControllerSignature.Generate(
                                timestamp, 
                                method, 
                                path, 
                                body, 
                                ModelConfig.Secret);  

                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    request.Headers.Add(HeaderNames.AccessKey,ModelConfig.Key);
                    request.Headers.Add(HeaderNames.AccessSign,sign);
                    request.Headers.Add(HeaderNames.AccessTimestamp,timestamp);
                    //request.Headers.Add(HeaderNames.AccessPassphrase,ModelConfig.Passphrase);
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var uaInfo = new ProductInfoHeaderValue(USER_AGENT_BOT_NAME, USER_AGENT_VERSION);
                    request.Headers.UserAgent.Add(uaInfo);  
                    var responseTask  = await client.SendAsync(request);                    
                    response = await responseTask.Content.ReadAsStringAsync();
                    //onsole.Write("Response is: " + response);  
                    return response;                                  
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("ControllerRequest, error is: " + e.Message);
            }

Screenshot 2023-12-06 at 2.23.17 PM

I don’t see any obvious error… Re-check API key, make sure it has wallet:accounts:read permission enabled.

2 Likes

Ok I’ll try to remove IP restriction and if that doesn’t work I’ll create a new key.

Removed IP restriction and still get unauthorized… I’ll try again with a new key. At this point, I have no clue.

Nope, tried with a new key and no IP restrictions on the key, same result.

I also selected all available permissions for each key I’ve tried…

Are you sure that new key was enabled? There might be 48h wait time…

Otherwise provide all data - api key, api secret (that is no longer valid!), timestamp, method, path and signature you are generating with these data. I will use your provided data and check what signature is generated by my code. That way you will know if your code generates correct signature or not.

EDIT: key is not needed as it is not used in signature generation!

2 Likes

Ok thanks, I will. I’ll send it soon.

Or you can use data from this example:

message:
1701895832GET/api/v3/brokerage/accounts
API secret:
abcd1234
signature:
df368f1d3d2339cd963cf613439cafed0b6bb342cec8c61184c75d3a7e55a73d
2 Likes

Make sure signature is in lower case.

2 Likes