401 error while using coinbase advanced trade

Hi mates, good morning !

I have a 401 Unauthorized error while using advanced trade API.

The code is in Scala using bits of Java.

val timestamp = Instant.now().getEpochSecond.toString
val body = Json.fromValues(Seq())
val requestPath = "/api/v3/brokerage/accounts";

val method = "GET";
val message = timestamp + method + requestPath  + "".toString()

val key = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")

val crypto = Mac.getInstance("HmacSHA256")
crypto.init(key)

val bytes = crypto.doFinal(message.getBytes(StandardCharsets.UTF_8))
val signature = Base64.getEncoder.encodeToString(bytes)
val apiUri = uri"https://api.coinbase.com/api/v3/brokerage/accounts"

  
val request = basicRequest.get(apiUri)
  .header("CB-ACCESS-KEY", apiKey)
  .header("CB-ACCESS-TIMESTAMP", timestamp)
  .header("CB-ACCESS-SIGN", signature)
  .header("Content-Type", "application/json")
  .header("Accept", "application/json")

//.body(body)
val backend = HttpURLConnectionBackend()
val response = request.send(backend)

// Parse response with Circe and execute trading logic
// You should also implement error handling here
IO(println(response))

Best regards,
Laurent

Hi @valdo404! Thank you for using Coinbase APIs. We will surely help you with this. Since you are getting a 401. Can you please confirm if it has been 48 hours or more from the time you created the API key? If it has not been, we would suggest you to wait, as the key activation takes 48 hours. If it has already been 48 hours and you are still getting the error 401, do let us know, and we will reach out to you with an update as soon as possible. Looking forward to your response.

Hi @Loop_11, I am doing about the same thing but getting:
HTTP 403

{"error":"unknown","error_details":"missing required scopes","message":"missing required scopes"}

Could you also look into this?

This is not the error format I was expecting based on the documentation:

{
  "error": "string",
  "code": "integer",
  "message": "string",
  "details": {
    "type_url": "string",
    "value": "string"
  }
}

https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getaccounts
Thank you

Hi @Loop_11 ,
My account did not have the accounts:read permission, however, can we clarify the error message formatting? I am using pydantic and the unmatching fields will create failures if the API is not compliant with the documentation - This could raise doubts as to what else is documented incorrectly, or incompletely

Thank you

Hi everyone, I have finally been able to correct my error. It was a problem with my Scala code and not with the token.

Here is the final Scala code based on sttp

  private def prepareCoinbaseRequest(requestPath: String, body: Option[Json]) = {
    import sttp.client3.circe._

    val timestamp = (Instant.now().toEpochMilli / 1000).toString

    val message =
      (timestamp +
      (if(body.isEmpty) "GET" else "POST") +
      requestPath +
      body.map(_.noSpaces).getOrElse(""))

    val key = new SecretKeySpec(Credentials.apiSecret.getBytes(UTF_8), HmacAlgorithm)

    val crypto: Mac = Mac.getInstance(HmacAlgorithm)
    crypto.init(key)

    val bytes = crypto.doFinal(message.getBytes(UTF_8))

    val apiUri = Uri.unsafeParse(s"$baseUrl$requestPath")

    val baseRequest = body.map(b => basicRequest.post(apiUri).body(b)).getOrElse(basicRequest.get(apiUri))

    baseRequest
      .header("CB-ACCESS-KEY", Credentials.apiKey)
      .header("CB-ACCESS-TIMESTAMP", timestamp)
      .header("CB-ACCESS-SIGN", bytes.map("%02x".format(_)).mkString.toLowerCase())
      .header("Content-Type", "application/json")
      .header("Accept", "application/json")
      .response(asJson[Json])
  }

Best

2 Likes