pythongoogle-apps-scriptgoogle-gemini

Gemini API: "InvalidSignature" in App Scripts


I am attempting to call Gemini API using App Scripts but I am consistently getting the 'InvalidSignature' error message. The code that I am using is a conversion of the python code from their documentation for Private API Invocation.

Code:

function createHeaders(payload) {
  var geminiApiKey = API_KEY
  var geminiApiSecret = SECRET_KEY
  var encodedApiSecret = Utilities.newBlob(geminiApiSecret, 'UTF-8').getBytes()

  var payloadNonce = new Date().getTime() / 1000;
  payload["nonce"] = Math.round(payloadNonce);

  var encodedPayload = Utilities.newBlob(JSON.stringify(payload), 'UTF-8').getBytes()
  var b64 = Utilities.base64Encode(encodedPayload) //string

  var signature = Utilities.computeHmacSignature(
    Utilities.MacAlgorithm.HMAC_SHA_384,
    b64,
    geminiApiSecretAuditor 
  ) //bytes

  return {
    "Content-Type": "text/plain",
    "X-GEMINI-APIKEY": geminiApiKeyAuditor,
    "X-GEMINI-PAYLOAD": b64,
    "X-GEMINI-SIGNATURE": Utilities.base64Encode(signature), //string
    "Cache-Control": "no-cache"
  };
}

function fetchGeminiData() {
  var baseUrl = "https://api.gemini.com";
  var url = baseUrl + "/v1/mytrades";

  var payload = {
    "request": "/v1/mytrades"
  };

  var headers = createHeaders(payload);
  var options = {
    "method": "post",
    "headers": headers,
  };

  var response = UrlFetchApp.fetch(url, options);
  var responseData = response.getContentText();
  var jsonResponse = JSON.parse(responseData);
  Logger.log(jsonResponse);
}

The error messages:

Exception: Request failed for https://api.gemini.com returned code 400. Truncated server response: {"result":"error","reason":"InvalidSignature","message":"InvalidSignature"}

I have ensured that the object types are as per what is expected from each methods, but I still get the above error messages. What am I missing?


Solution

  • I believe your goal is as follows.

    In this case, how about the following sample script?

    Sample script:

    function myFunction() {
      API_KEY = "mykey"; // Please set your api key.
      SECRET_KEY = "1234abcd"; // Please set your secret.
    
      var gemini_api_key = API_KEY;
      var gemini_api_secret = SECRET_KEY;
    
      var baseUrl = "https://api.gemini.com";
      var url = baseUrl + "/v1/mytrades";
      var nonce = (new Date().getTime() / 1000).toString();
      var payload = `{"request": "/v1/mytrades", "nonce": "${nonce}"}`;
      var b64 = Utilities.base64Encode(payload);
      var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384, b64, gemini_api_secret).map(b => ('0' + (b & 0xFF).toString(16)).slice(-2)).join('');
      var request_headers = {
        'Content-Type': "text/plain",
        'X-GEMINI-APIKEY': gemini_api_key,
        'X-GEMINI-PAYLOAD': b64,
        'X-GEMINI-SIGNATURE': signature,
        'Cache-Control': "no-cache"
      };
      var options = { method: "post", headers: request_headers };
      var response = UrlFetchApp.fetch(url, options);
      var responseData = response.getContentText();
      var jsonResponse = JSON.parse(responseData);
      console.log(jsonResponse);
    }
    

    Note:

    Reference: